Friday, June 1, 2012

How do I iterate over each Entry in a 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?


Source: Tips4all

10 comments:

  1. for (Map.Entry<String, String> entry : map.entrySet())
    {
    System.out.println(entry.getKey() + "/" + entry.getValue());
    }

    ReplyDelete
  2. 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();
    // ...
    }

    ReplyDelete
  3. This is a two part question:

    How to iterate over the entries of a Map - @ScArcher2 has answered 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, ceilingEntry, or floorEntry methods. The descendingMap method even gives you an explicit method of reversing the traversal order.

    ReplyDelete
  4. 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.

    ReplyDelete
  5. 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.

    ReplyDelete
  6. The correct way to do this is to use the accepted answer as it is the most efficient. I find the following code looks a bit cleaner.

    for (String key: map.keySet()) {
    System.out.println(key + "/" + map.get(key));
    }

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

    ReplyDelete
  8. 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());

    //...


    }

    ReplyDelete
  9. 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.

    ReplyDelete
  10. public class abcd{
    public static void main(String[] args)
    {
    Map<Integer, String> testMap = new HashMap<Integer, String>();
    testMap.put(10, "a");
    testMap.put(20, "b");
    testMap.put(30, "c");
    testMap.put(40, "d");
    for (Integer key:testMap.keySet()) {
    String value=testMap.get(key);
    System.out.println(value);
    }
    }
    }


    OR

    public class abcd {
    public static void main(String[] args)
    {
    Map<Integer, String> testMap = new HashMap<Integer, String>();
    testMap.put(10, "a");
    testMap.put(20, "b");
    testMap.put(30, "c");
    testMap.put(40, "d");
    for (Entry<Integer, String> entry : testMap.entrySet()) {
    Integer key=entry.getKey();
    String value=entry.getValue();
    }
    }
    }

    ReplyDelete