Chapter 7 - Java for Beginners Course

Map and HashMap - Basic Operations

In the previous section we covered the theory behind hash tables, the foundation behind the HashMap class, a specific implementation of the Map interface in Java.

The Map interface represents data structures that are meant to keep a map from a key to a value, however, Map doesn’t impose any specific implementation.

In this section we’ll cover some of the basic operations offered by the Map interface using HashMap as the concrete implementation for the examples.

Another common implementation of Map<K, V> is TreeMap<K,V> which we’ll not cover in this beginners course.

The Map<K, V> interface

The Map interface is a generic interface that defines two type parameters <K, V>. K represents the type of element for the keys and V the type of elements for the values.

As stated in the documentation, maps can’t contain duplicate keys and each key can only map to a single value.

To clarify what we mean by this, we’ll use the UserId → User map that we used in the previous section.

For this purpose, let’s assume we have a User class defined as follows:

public class User {
    private final int userId;

    private final String name;

    public User(int userId, String name) {
        this.userId = userId;
        this.name = name;
    }

    public int getUserId() {
        return userId;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "User [userId=" + userId + ", name=" + name + "]";
    }
}
In the example code run the JavaBasicHashMapApp

Creating a HashMap

Let’s create a HashMap object to store our mappings for the user example. In this case, our keys are going to be the ids of the users which are of type int and our values are going to be our User objects:

Map<Integer, User> userMap = new HashMap<>();
System.out.println("Initial size of the map: " + userMap.size());

Output:

Initial size of the map: 0
Remember we can’t use primitive types like int as generic types. Hence, for int we use its wrapper class Integer.

Adding mappings

The basic method to insert/add a new key → value mapping is put(key, value) in the Map interface. For example, to add the mapping for 100 → User [id=100, name="Andy G."], we’d do the following:

User user = new User(100, "Andy G.");
userMap.put(user.getUserId(), user);

We’ll do the same for the remaining 3 users in the example from the previous section:

User user2 = new User(244, "Jess J.");
userMap.put(user2.getUserId(), user2);

User user3 = new User(315, "Josh N.");
userMap.put(user3.getUserId(), user3);

User user4 = new User(9, "Paul D.");
userMap.put(user4.getUserId(), user4);

Getting the value for a given key

To retrieve the value that is stored/associated for a particular key, we use the get(key) method, for example, if we want to check what user is mapped to id 244:

User mappedUser = userMap.get(244);
System.out.println(mappedUser);

Output:

User [userId=244, name=Jess J.]

In a similar way, if a given key isn’t mapped to any value we’ll get a null return value, for example:

User mappedUser2 = userMap.get(1000);
System.out.println(mappedUser2);

Output:

null

Checking if a key exists

Another common operation is verifying if a key has already been defined/added to a map before performing other operations. To do this we make use of the containsKey(key) method, for example, to print out a line only if key=100 exists in the map:

if (userMap.containsKey(100)) {
    System.out.println("Key 100 exists in the userMap");
}

Output:

Key 100 exists in the userMap

Removing a mapping

The last operation we’ll cover in this section is how to remove/delete a key → value mapping. To do this, we’ll use the remove(key) method, for example, to remove the mapping for key 100:

userMap.remove(100);

Now, if we check if the userMap doesn’t contain the key, we’d get the following result:

if (!userMap.containsKey(100)) {
    System.out.println("Key 100 doesn't exist in the userMap");
}

Output:

Key 100 doesn't exist in the userMap
Note the difference in the if statements in the two examples above. In the first one we’re checking if the key exists, in the second one we’re checking if the key doesn’t exist using the complement operator (!).

Multimaps

One of the restrictions of the Map interface states that a key can only map to a single value. However, there will be occasions when you might need to map a key to multiple values.

A common approach to this problem is to use a collection of elements as the value to be stored. For example, if you want to map the name (String) of a person to one or more phone numbers (assume each phone number is represented by an object of class PhoneNumber), you could think about building a map like this one:

Map<String, List<PhoneNumber>> contactList = new HashMap<>();