1. A set of key-value pairs.
In Java, another interesting collection (broadly speaking) is Map
. Sometimes this data structure is also called a dictionary.
It is similar to the Set
collection, but it stores a set of "pairs" of elements rather than a set of elements, Each pair in a Map
consists of two elements: a "key" and a "value".
Let's say you want your program to store employee names and their salaries, or your coworkers names and their ages. Then you would need a table like this:
Name | Age |
---|---|
Elon | 21 |
Jeff | 22 |
Bill | 48 |
Warren | ? |
Each row contains a couple of values. We will refer to the name as the pair's key, and the age as the pair's value.
The whole set of these pairs is our map (Map
).
A pair's key can be anything, but for some types of maps the key cannot be null
. Keys must be unique: one map cannot contain two identical keys.
2. HashMap
class
The HashMap
class is the most popular kind of Map
collection. On the one hand, it is very similar to HashSet and has all its methods. On the other hand, it is like a list (ArrayList
) that can use words (or anything else) as its indices.
You can create a HashMap
using a statement like this:
HashMap<KeyType, ValueType> name = new HashMap<KeyType, ValueType>();
Where KeyType
is the type of the keys in the stored pairs, and ValueType
is the type of the values in the pairs stored in the HashMap
collection.
The HashMap
class has methods like this:
Method | Description |
---|---|
|
Adds the (key , value ) pair to the collection |
|
Returns the value associated with a key. |
|
Checks whether a key exists in the collection |
|
Checks for the existence of a value in the collection |
|
Removes an element from the collection |
|
Clears the collection, removing all the elements |
|
Returns the number of key-value pairs in the collection |
|
Returns the set of keys in the collection |
|
Returns a set containing the elements of the collection |
|
Returns a set (Set ) of all pairs (Map.Entry ) in the collection. |
Adding elements to a HashMap
Elements are added to a map as pairs using the put()
method. The key is passed as the first argument, and the value is passed as the second.
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("Elon", 21);
map.put("Jeff", 22);
map.put("Bill", 48);
map.put("Warren", null);
When adding a key-value pair, if the key already exists in the collection, then the old value is replaced by the new value.
This behavior makes a HashMap
like an array or a list whose indices are words (String
) instead of numbers.
Almost any type can be the KeyType or ValueType. There are some small additional requirements for the KeyType, and you will learn about them when you study collections in greater detail in the Java Collections quest.
3. Subsets of a HashMap
: the set of keys
Let's say we just want to display all the entries in a HashMap
on the screen. How do we do this? To do this, we need to know how to go through all the entries in the HashMap
. This can be done in several ways.
The easiest way is to loop over the keys
HashMap
entries are not numbered sequentially, so a loop with a counter won't work here. But we can get a set of keys using the keySet()
method, and you already know how to iterate over a set:
Code | Description |
---|---|
|
Loop over the keys of the map Get the value associated with the key |
The keySet()
method returns a set of keys. You can use this set in two ways:
Compact notation | Long notation |
---|---|
|
|
4. Looping over key-value pairs
There is also a more complicated way: you can transform a Map
into a set of key-value pairs, and then loop over the elements of the set, as we have already learned.
The HashMap
collection has a helper class that stores a key-value pair. It looks approximately like this:
class Entry<KeyType, ValueType>
{
private KeyType key;
private ValueType value;
public KeyType getKey()
{
return this.key;
}
public ValueType getValue()
{
return this.value;
}
}
The result of calling the entrySet()
method on a HashMap<KeyType, ValueType>
object will be a Set<Entry<KeyType, ValueType>>
:
Set<Entry<KeyType, ValueType>> name = map.entrySet();
Here we have the generic Set
class with a type parameter, which in turn is a generic type (Entry
) with two type parameters.
It is very easy for a beginner to get confused about this. But once you figure it out, you can write code like:
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("Elon", 21);
map.put("Jeff", 22);
map.put("Bill", 48);
map.put("Warren", null);
Set<Map.Entry<String, Integer>> entries = map.entrySet();
for(Map.Entry<String, Integer> pair: entries)
{
String key = pair.getKey();
Integer value = pair.getValue();
System.out.println(key + " --> " + value);
}
That said, this code can be simplified a little:
First, you can skip creating a separate variable for entries
and instead call the entrySet()
method directly inside the for
loop:
for(Map.Entry<String, Integer> pair: map.entrySet())
{
String key = pair.getKey();
Integer value = pair.getValue();
System.out.println(key + " --> " + value);
}
Second, you can use the recently introduced var
operator to automatically infer the type of the key-value pair:
for(var pair: map.entrySet())
{
String key = pair.getKey();
Integer value = pair.getValue();
System.out.println(key + " --> " + value);
}
Not bad, eh?
5. Comparison of ArrayList
and HashMap
A HashMap
strongly resembles an ArrayList
that allows strings (or other types) to be used as indexes (the keys).
If you use Integer
for the keys in a HashMap
, then it becomes even more similar to an ArrayList
. Let's compare:
Code with ArrayList<String> | Code with HashMap<Integer, String> |
---|---|
|
|
GO TO FULL VERSION