[英]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.