簡體   English   中英

HashMap:以隨機順序迭代鍵值對

[英]HashMap: iterating the key-value pairs in random order

我有一個HashMap,每當我得到迭代器時,我想以不同的隨機順序迭代它們的鍵值對。 從概念上講,我想在調用迭代器之前“洗牌”地圖(或者如果你想要,“洗牌”迭代器)。

我有兩個選擇:

1)使用LinkedHashMap的方法並在內部保留一個條目列表,將其隨地移動並在調用迭代器時返回該視圖。
2)取map.entrySet(),構造一個ArrayList並在其上使用shuffle()。

雖然這兩種方法看起來與我類似,但我期待非常大的HashMaps,所以我真的很關心細節和內部因素,因為我真的不能浪費內存或計算。

重新整理大型收藏品總是很昂貴。 每個條目至少需要一個引用。 例如,對於100萬個條目,您將需要大約4 MB。

注意; 洗牌操作是O(N)

我會用

Map<K,V> map = 
List<Map.Entry<K,V>> list = new ArrayList<Map.Entry<K,V>>(map.entrySet());

// each time you want a different order.
Collections.shuffle(list);
for(Map.Entry<K, V> entry: list) { /* ... */ }

實際上你根本不需要洗牌:
只需在鍵數組中繪制一個隨機索引,然后通過覆蓋最后一個鍵來刪除鍵:

public class RandomMapIterator<K,V> implements Iterator<V> {

private final Map<K,V> map;
private final K[] keys;

private int keysCount;

@SuppressWarnings("unchecked")
public RandomMapIterator(Map<K,V> map) {
    this.map = map;
    this.keys = (K[]) map.keySet().toArray();
    this.keysCount = keys.length;
}

@Override
public boolean hasNext() {
    return keysCount!=0;
}

@Override
public V next() {
    int index = nextIndex();
    K key = keys[index];
    keys[index] = keys[--keysCount];
    return map.get(key);
}

protected int nextIndex() {
    return (int)(Math.random() * keysCount);
}

@Override
public void remove() {
    throw new UnsupportedOperationException();
}

}

嘗試使用concurent哈希映射並在迭代周期之前隨機獲取密鑰

Map<String, String> map = Maps.newConcurrentMap();

        map.put("1", "1");
        map.put("2", "2");
        Iterator<String> iterator = map.keySet().iterator();
        while (iterator.hasNext()) {
            map.remove("2");// add random key values
            map.put("2", "2");
            String next = iterator.next();
            System.out.println("next" + next);
        }

隨機刪除/放置值可以“改變”您的地圖

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM