views:

11694

answers:

9
+25  Q: 

Iterate Over Map

If I have an object implementing the Map interface in Java and I wish to iterate over every pair contained within it, what is the most efficient way of going through the map? Will the ordering of elements depend on the specific map implementation that I have for the interface?

+13  A: 

Yes, the order depends on the specific Map implementation.

@ScArcher2 has the more elegant Java 1.5 syntax. In 1.4, I would do something like this:

Iterator entries = myMap.entrySet().iterator();
while (entries.hasNext()) {
  Entry thisEntry = (Entry) entries.next();
  Object key = thisEntry.getKey();
  Object value = thisEntry.getValue();
  // ...
}
pkaeding
Prefer for-loop than while..for(Iterator entries = myMap.entrySet().iterator(); entries.hasNext(); ) {...}With this syntax the 'entries' scope is reduced to the for loop only.
HanuAthena
+48  A: 
for (Map.Entry<String, String> entry : map.entrySet())
{
    System.out.println(entry.getKey() + "/" + entry.getValue());
}
ScArcher2
I think you should remove the 'Map.' before 'Map.Entry' so the for becomes "for (Entry<String, String> entry : map.entrySet())"
Roalt
If you do that, then it won't work as Entry is a nested Class in Map.http://java.sun.com/javase/6/docs/api/java/util/Map.html
ScArcher2
@ScArcher2 you can write the import as "import java.util.Map.Entry;" and it will work.
jjujuma
@jjujuma cool that's good to know!
ScArcher2
A: 

In theory, the most efficient way will depend on which implementation of Map. The official way to do this is to call map.entrySet(), which returns a set of Map.Entry, each of which contains a key and a value (entry.getKey() and entry.getValue()).

In an idiosyncratic implementation, it might make some difference whether you use map.keySet(), map.entrySet() or something else. But I can't think of a reason why anyone would write it like that. Most likely it makes no difference to performance what you do.

And yes, the order will depend on the implementation - as well as (possibly) the order of insertion and other hard-to-control factors.

[edit] I wrote valueSet() originally but of course entrySet() is actually the answer.

Leigh Caldwell
+7  A: 

Typical code for iterating over a map is:

Map<String,Thing> map = ...;
for (Map.Entry<String,Thing> entry : map.entrySet()) {
    String key = entry.getKey();
    Thing thing = entry.getValue();
    ...
}

HashMap is the canonical map implementation and doesn't make guarantees (or though it should not change order if no mutating operation are performed on it). SorterMap will return entries on however the map sorts the keys. LinkedHashMap will either return entries in insertion-order or access-order depending upon how it has been constructed. EnumMap returns entries in natural order of keys.

Note, IdentityHashMap entrySet iterator currently has a peculiar implementation which returns the same Map.Entry instance for every item in the entrySet! However, every time a new the iterator advances the Map.Entry is updated.

Tom Hawtin - tackline
+11  A: 

This is a two part question:

How to iterate over the entries of a Map - @ScArcher2 has asnwered that perfectly.

What is the order of iteration - if you are just using Map, then strictly speaking, there are no ordering guarantees. So you shouldn't really rely on the ordering given by any implementation. However, the SortedMap interface extends Map and provides exactly what you are looking for - implementations will aways give a consistent sort order.

NavigableMap is another useful extension - this is a SortedMap with additional methods for finding entries by their ordered position in the key set. So potentially this can remove the need for iterating in the first place - you might be able to find the specific entry you are after using the higherEntry, lowerEntry, celingEntry or floorEntry methods. The descendingMap method even gives you an `explicit method of reversing the traversal order.

serg10
+1 for mentioning NavigableMap, news to me
Jason S
+2  A: 

FYI, you can also use map.keySet() and map.values() if you're only interested in keys/values of the map and not the other.

sundae1888
+2  A: 

I typically do it by iterating over the keyset instead of the entry set. I find the code looks a bit cleaner. You also know that you are always looking at items in keys order for ordered maps such as the LinkedHashMap:

for (String key: map.keySet()) {
   System.out.println(key + "/" + map.get(key));
}
Chris Dail
This is not the best approach, it's much more efficient to use the entrySet(). Findbugs will flag this code (see http://findbugs.sourceforge.net/bugDescriptions.html#WMI_WRONG_MAP_ITERATOR)
Jeff Olson
A: 

Example of using iterator and generics:

Iterator<Map.Entry<String, String>> entries = myMap.entrySet().iterator();
while (entries.hasNext()) {
  Map.Entry<String, String> entry = entries.next();
  String key = entry.getKey();
  String value = entry.getValue();
  // ...
}
serg
A: 

try this with java 1.4

for( Iterator entries = myMap.entrySet().iterator(); entries.hasNext();){

   Entry entry = (Entry) entries.next();

  System.out.println(entry.getKey() + "/" + entry.getValue());

   //...

}

abods