1. Overview

We often use maps to store a collection of key-value pairs. Then, at some point, we often need to iterate over them.

In this tutorial, we’ll compare different methods of map iteration, highlighting when it may be beneficial to use Map.Entry. Then, we’ll learn how Map.Entry can be used to create a tuple. Finally, we’ll create an ordered list of tuples.

2. Optimizing Map Iteration

Suppose that we have a map of book titles with the author’s name as the key:

Map<String, String> map = new HashMap<>();

map.put("Robert C. Martin", "Clean Code");
map.put("Joshua Bloch", "Effective Java");

Let’s compare two methods of getting all the keys and values from our map.

2.1. Using Map.keySet

First, consider the following:

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

Here, the loop iterates over keySet. For each key, we get the corresponding value using Map.get. While this is an obvious way to use all of the entries in the map, it requires two operations for each entry — one to get the next key and one to look up the value with get.

If we need just the keys in a map, keySet is a good option. However, there’s a faster way to get both the keys and values.

2.2. Using Map.entrySet Instead

Let’s rewrite our iteration to use entrySet:

for (Map.Entry<String, String> book: bookMap.entrySet()) {
    System.out.println("key: " + book.getKey() + " value: " + book.getValue());
}

In this example, our loop is over a collection of Map.Entry objects. As Map.Entry stores both the key and value together in one class, we get them both in a single operation.

The same rules apply to using Java 8 stream operations. Streaming over the entrySet and working with Entry objects is more efficient and can require less code.

3. Working With Tuples

A tuple is a data structure that has a fixed number and order of elements. We can think of Map.Entry is a tuple that stores two elements – a key and a value. However, as Map.Entry is an interface, we require an implementation class. In this section, we’ll explore one implementation provided by the JDK: AbstractMap.SimpleEntry.

3.1. Creating a Tuple

First, consider the Book class:

public class Book {
    private String title;
    private String author;

    public Book(String title, String author) {
        this.title = title;
        this.author = author;
    }
    ...

Next, let’s create a Map.Entry tuple with the ISBN as the key and the Book object as the value:

Map.Entry<String, Book> tuple;

Finally, let’s instantiate our tuple with AbstractMap.SimpleEntry:

tuple = new AbstractMap.SimpleEntry<>("9780134685991", new Book("Effective Java 3d Edition", "Joshua Bloch"));

3.2. Creating an Ordered List of Tuples

When working with tuples, it’s often useful to have them as an ordered list.

First, we’ll define our list of tuples:

List<Map.Entry<String, Book>> orderedTuples = new ArrayList<>();

Secondly, let’s add some entries to our list:

orderedTuples.add(new AbstractMap.SimpleEntry<>("9780134685991", 
  new Book("Effective Java 3d Edition", "Joshua Bloch")));
orderedTuples.add(new AbstractMap.SimpleEntry<>("9780132350884", 
  new Book("Clean Code","Robert C Martin")));

3.3. Comparing With a Map

In order to compare the differences with a Map, let’s add a new entry with a key that already exists:

orderedTuples.add(new AbstractMap.SimpleEntry<>("9780132350884", 
  new Book("Clean Code", "Robert C Martin")));

Secondly, we’ll iterate over our list, displaying all the keys and values:

for (Map.Entry<String, Book> tuple : orderedTuples) {
    System.out.println("key: " + tuple.getKey() + " value: " + tuple.getValue());
}

Finally, let’s see the output:

key: 9780134685991 value: Book{title='Effective Java 3d Edition', author='Joshua Bloch'}
key: 9780132350884 value: Book{title='Clean Code', author='Robert C Martin'}
key: 9780132350884 value: Book{title='Clean Code', author='Robert C Martin'}

Notice that we can have duplicate keys, unlike a basic Map, where each key has to be unique. This is because we’ve used a List implementation to store our SimpleEntry objects, which means all the objects are independent of each other.

3.4. Lists of Entry Objects

We should note that the purpose of Entry is not to act as a generic tuple. Library classes often provide a generic Pair class for this purpose.

However, we may find that we need to temporarily work with lists of entries while preparing data for a Map or extracting data from one.

4. Conclusion

In this article, we looked at Map.entrySet as an alternative to iterating over a map’s keys.

We then looked at how Map.Entry can be used as a tuple.

Finally, we created a list of ordered tuples, comparing the differences to a basic Map.

As always, the example code is available over on GitHub.


« 上一篇: JVM常量池介绍