Skip to main content

Section 3.3 The Map interface and HashMap class

As we mentioned earlier in the section, maps are used to hold key-value pairs. As such, in order to use a map we need to specify two classes: One for the keys, typically strings, and one for the values. Similar to the List/ArrayList situation, we have the interface Map, which prescribes what kinds of functions we have, and the class HashMap, which provides an implementation of those functions.
Let’s take a look at an example of a map that actually does something useful: Given a list of words, it counts how many times each word occurs. Then it prints those counts.
List<String> words = // ... A list of words here
Map<String, Integer> wordCounts = new HashMap<>();
for (String word : words) {
  int currentCount = wordCounts.getOrDefault(word, 0);
  wordCounts.put(word, currentCount + 1);
}
for (Map.Entry<String, Integer> entry : wordCounts.entrySet()) {
  System.out.printf("%s: %d%n", entry.getKey(), entry.getValue());
}
There’s a lot to cover here, so let’s get started.
  • Line 2 creates a new Map called wordCounts. By the angle bracket specification of String, Integer we learn that this map uses String keys and stores Integer values.
  • The map is initialized as an empty HashMap by calling that class’ constructor.
  • In lines 3-5 we iterate over the list of words. We first use a convenient method that maps provide, called getOrDefault, which looks up the value for a provided key and if it is not found then it uses the provided default value, in our case 0. The end result is that the currentCount variable will contain the number of times we have seen this word so far.
    Then in line 5 we increment that value by 1 and store the result using the map method put.
    We could have done this loop in a few other ways, I encourage you to look at the Map documentation for the various functions provided.
  • The next interesting part is lines 6-8. There we iterate over the map, then print the results. The first tricky bit is how to iterate. This is done by asking for the map’s entrySet, which is in effect a list of objects of class Map.Entry. This is a very simple class that holds two fields, key and value. So for every key-value pair in our map, we will have one of these objects provided to us in the loop.
  • Lastly, we learn about a new method for printing formatted information, namely System.out.printf. It expects a format string
     1 
    docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Formatter.html
    as the first argument, and then uses the subsequent arguments as value fillers. In this case we use %s for a string and %d for an integer.
If you try this little bit of code with a list of words, you should be able to run it and see a nice output.

Checkpoint 3.3.1.

Rearrange the following blocks so that they form a function that takes as input a list of words. It then goes through the words and uses a map to keep track of how many times it has seen each word. When it sees a word that it has seen before, it prints a message about how many times the word has been seen. All blocks will be used.