繁体   English   中英

将大量键映射到一小组值

[英]Mapping large set of Keys to a small set of Values

如果您有1,000,000个密钥(整数)映射到10,000个值(整数)。 实现什么是最有效的方法(查找性能和内存使用)。

假设值是随机的。 即,没有一系列键映射到单个值。

我能想到的最简单的方法是HashMap,但想知道你是否可以通过对匹配单个值的键进行分组来做得更好。

Map<Integer,Integer> largeMap = Maps.newHashMap();
largeMap.put(1,4);
largeMap.put(2,232);
...
largeMap.put(1000000, 4);

如果已知该组键在给定范围内(如示例中所示为1-1000000),则最简单的方法是使用数组。 问题是您需要按键查找值,这会将您限制为地图或数组。

以下使用值的值映射只是为了避免重复的等值对象实例(可能有更好的方法来做到这一点,但我想不出任何)。 该数组仅用于按索引查找值:

private static void addToArray(Integer[] array, int key, 
        Integer value, Map<Integer, Integer> map) {

    array[key] = map.putIfAbsent(value, value);
}

然后可以使用以下命令添加值:

Map<Integer, Integer> keys = new HashMap<>();
Integer[] largeArray = new Integer[1000001];

addToArray(largeArray, 1, 4, keys);
addToArray(largeArray, 2, 232, keys);
...
addToArray(largeArray, 1000000, 4, keys);

如果new Integer[1000001]看起来像是一个hack,你仍然可以保持一种“索引偏移”来指示与数组中的索引0相关联的实际键。


我会把它放在一个班级:

class LargeMap {

    private Map<Integer, Integer> keys = new HashMap<>();
    private Integer[] keyArray;

    public LargeMap(int size) {
        this.keyArray = new Integer[size];
    }

    public void put(int key, Integer value) {
        this.keyArray[key] = this.keys.putIfAbsent(value, value);
    }

    public Integer get(int key) {
        return this.keyArray[key];
    }
}

和:

public static void main(String[] args) {
    LargeMap myMap = new LargeMap(1000_000);

    myMap.put(1, 4);
    myMap.put(2, 232);
    myMap.put(1000_000, 4);
}

我不确定你是否可以通过分组任何东西来优化。 如果你想通过值而不是按键进行查找(即获取具有特定值的所有键),“反向”映射可能会给你稍微好一点的性能但是因为你没有明确表示你想要这样做我不会'采用这种方法。

对于优化,如果键位于固定范围内,则可以使用int数组而不是map。 数组查找是O(1),原始数组使用的内存少于映射。

int offset = -1;
int[] values = new int[1000000];
values[1 + offset] = 4;
values[2 + offset] = 232;
// ...
values[1000000 + offset] = 4;

如果范围不是从1开始,则可以调整偏移量。

还有像trove4j这样的库,它们为这类数据提供比标准集合更好的性能和更高效的存储,但我不知道它们与简单数组方法的比较。

HashMap是最糟糕的解决方案。 整数的哈希本身就是哈希。 如果你想要一个容易获得的解决方案,我会说一个TreeMap。 您可以编写自己的专用树图,例如将键拆分为两个短路并在Treemap中具有TreeMap。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM