java data-structures random iterator hashmap

java - HashMap: iteración de los pares clave-valor en orden aleatorio



data-structures random (3)

Tengo un HashMap y me gustaría iterar los pares clave-valor en un orden aleatorio diferente cada vez que obtengo el iterador. Conceptualmente me gustaría "mezclar" el mapa antes de llamar al iterador (o si lo desea, "mezclar" el iterador).

Tengo dos opciones que veo:

1) utilice el enfoque de LinkedHashMap y mantenga una lista de las entradas internamente, remezclarla en el lugar y devolver esa vista cuando se llame al iterador.
2) tome map.entrySet (), construya una ArrayList y use shuffle () en ella.

Si bien los dos enfoques parecen muy similares a mí, espero VERY BIG HashMaps, así que estoy realmente preocupado por los detalles y el funcionamiento interno, ya que realmente no estoy en posición de malgastar la memoria O el cálculo.


Intente usar el mapa concurent hash y obtenga la clave al azar antes del ciclo de iteración

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); }

Los valores de quitar / poner aleatorios pueden "mezclar" su mapa


La remodelación de una gran colección siempre será costosa. Necesitará al menos una referencia por entrada. por ejemplo, para 1 millón de entradas, necesitarás aproximadamente 4 MB.

Nota; la operación de mezcla es O(N)

yo usaría

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) { /* ... */ }


En realidad, no es necesario mezclar nada:
Simplemente dibuje un índice al azar en una matriz de teclas y elimine la clave sobrescribiendo con la última:

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(); }

}