Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HashMap: iterating the key-value pairs in random order

I have a HashMap and I'd like to iterate they key-value pairs in a different random order each time i get the iterator. Conceptually I'd like to "shuffle" the map before calling the iterator (or if you want, "shuffle" the iterator).

I have two options i see:

1) use the approach of LinkedHashMap and keep a list of the entries internally, shuffle it in-place and return that view when the iterator is called.
2) take map.entrySet(), construct an ArrayList and use shuffle() on it.

While the two approaches look vey similar to me, I'm expecting VERY BIG HashMaps, so I'm really concerned on details and internals, as I'm really not in a position to waste memory OR computation.

like image 679
marcorossi Avatar asked Oct 10 '12 08:10

marcorossi


People also ask

Does HashMap iterate in order?

The HashMap in Java provides good performance but doesn't maintain any order of its elements. If you want insertion-order iteration with near-HashMap performance, you can use LinkedHashMap . If you want sorted-order iteration, you can use the TreeMap implementation of the Map interface.

Does HashMap store keys in order?

As we know that Hash map in Java does not maintain insertion order either by key or by order. Also it does not maintain any other order while adding entries to it.

Can you shuffle a HashMap?

There is no point to shuffle the keys of HashMap since HashMap doesn't preserve any order (neither natural nor insert) in its keys. Question makes sense if we're talking about LinkedHashMap, which maintains insertion order. In such a case you can create a new LinkedHashMap having the keys inserted randomly.


1 Answers

Reshuffling a large collection is always going to be expensive. You are going to need at least one reference per entry. e.g. for 1 million entries you will need approx 4 MB.

Note; the shuffle operation is O(N)

I would use

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) { /* ... */ }
like image 54
Peter Lawrey Avatar answered Oct 15 '22 01:10

Peter Lawrey