神刀安全网

Iterating Java Map Entries

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 are a number of ways to do this in Java, and that number has 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 (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<String> 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 that by 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, which is 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<String> 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, the cast is gone now, 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<String> 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 have given you three 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.

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » Iterating Java Map Entries

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址