HashMap:以随机顺序迭代键值对

我有一个HashMap,我想在每次获得迭代器时以不同的随机顺序迭代它们的键值对。 从概念上讲,我想在调用迭代器之前“洗牌”地图(或者如果你想要,“洗牌”迭代器)。

我有两种选择:

1)使用LinkedHashMap的方法并在内部保留条目列表,将其随地移动并在调用迭代器时返回该视图。
2)取map.entrySet(),构造一个ArrayList并在其上使用shuffle()。

虽然这两种方法看起来很像我,但我期待非常大的HashMaps,所以我真的很关心细节和内部,因为我真的不能浪费内存或计算。

重新整理大型collections品总是很昂贵。 每个条目至少需要一个引用。 例如,对于100万个条目,您将需要大约4 MB。

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

我会用

 Map map = List> list = new ArrayList>(map.entrySet()); // each time you want a different order. Collections.shuffle(list); for(Map.Entry entry: list) { /* ... */ } 

实际上你根本不需要洗牌:
只需在键数组中绘制一个随机索引,然后通过覆盖最后一个键来删除键:

 public class RandomMapIterator implements Iterator { private final Map map; private final K[] keys; private int keysCount; @SuppressWarnings("unchecked") public RandomMapIterator(Map 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 map = Maps.newConcurrentMap(); map.put("1", "1"); map.put("2", "2"); Iterator 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); } 

随机删除/放置值可以“改变”您的地图