Iterating Java Map Entries

Iterating Java Map Entries

3 Comments

The majority of the time when you’re working with Maps in Java, you’ll be accessing the map values via the key. There are times you need to walk the map like a list. There’s a number of ways to do this in Java, which have grown over time as the language has evolved.

Let’s take a closer look at walking over Map entries in Java using JUnit. For the series of examples below, I’m going to prepare a map for each test like this:

Map<Integer, String> map;

@Before
public void setup(){
    map = new HashMap<>();
    map.put(1, "Java");
    map.put(2, "Groovy");
    map.put(3, "Scala");
    map.put(4, "Clojure");
    map.put(5, "jRuby");
}

This is a simple HashMap in Java. I’m using generics to say the Map key is an integer, and the Map value is a String. For this example, I’m creating a map with some of the various JVM languages.

Using an Iterator over Map Entries

If you’re still stuck using Java 1.4, you might use an Iterator to walk the Map entries. But hopefully, you’re not still on Java 1.4! But there is plenty of legacy code out there still doing this.

Here is an example of using an Iterator over a map. I’m tossing in the use of Generics, so this code snippet is not Java 1.4 compliant. I’m also using the older style while loop.

@Test
public void testMapWithIterator() throws Exception {
    List jvmLangs = new ArrayList<>();

    Iterator iterator = map.entrySet().iterator();

    while (iterator.hasNext()){
        Map.Entry<Integer, String> entry  = (Map.Entry<Integer, String>) iterator.next();

        jvmLangs.add(entry.getValue());
    }

    assert jvmLangs.size() == 5;
}

You can see is using this technique, I need to do a cast:

(Map.Entry<Integer, String>) iterator.next();

I cringe a little every time I need to do a hard cast like this. It’s generally a code smell.

Using For Each over Map Entries

Java 1.5 gave us for each loops. A much nicer syntax for doing loop operations. Here is an example of using a for each loop over Map entries.

    @Test
    public void testMapIteration(){
        List jvmLangs = new ArrayList<>();

        for (Map.Entry<Integer, String> entry : map.entrySet()){
            jvmLangs.add(entry.getValue());
        }

        assert jvmLangs.size() == 5;
    }

You can see the code is a little cleaner now. Also gone now is the cast, so this code smells better!

Using Java 8’s forEach over Map Entries

While the Java 7 release was rather boring for developers, Java 8 has brought us some really nice features to work with. We have a new forEach statement we can use in conjunction with lambdas. Here is an example of using Java 8 lambdas to iterate over Map entries.

@Test
public void testMapIteration() {
    List langs = new ArrayList<>();

    map.forEach((k, v) -> langs.add(v));

    assert langs.size() == 5;
}

You can see Java 8 really allows us to clean up the code. No casts here. You can also see we’re skipping over explicitly dealing with the Map.Entry object in the lambda. Even though we’re taking a shortcut here, we still have the type safety of Java.

Conclusion

I given you 3 different ways of walking over a list of map entries in Java. In my examples here you can see how the code has become cleaner as the Java programming language has evolved over the years.

About jt

    You May Also Like

    3 comments on “Iterating Java Map Entries

    1. May 12, 2016 at 3:30 pm

      To make your java 1.7 and lower versions a bit better, maybe use map.keySet() instead of map.entrySet()?

      Reply
    2. May 18, 2016 at 3:49 am

      i think there’s no point iterating on a map, maps are intended for O(1) access via its key, if you need a set use a Set, List, etc…

      Reply
      • May 21, 2016 at 7:18 am

        It’s actually a rather common task to walk over the entries in a map. Lots of use cases for this.

        Reply

    Leave a Reply

    Your email address will not be published. Required fields are marked *

    This site uses Akismet to reduce spam. Learn how your comment data is processed.