Tech and Media Labs
This site uses cookies to improve the user experience.




Generic Map in Java

Jakob Jenkov
Last update: 2015-09-02

Java's Map interface (java.util.Map) can be generified. In other words, you can set the specific type of both the keys and values in a generic Map instance. Here is an example:

Map<Integer, String> set = new HashMap<Integer, String>;

This Map can now only accept Integer instances as keys, and String instances as values.

The generic type checks only exists at compile time. At runtime it is possible to tweak your code so that other instances can be inserted. This is a bad idea, though.


Accessing a Generic Map

Adding and getting elements to a generic Map is done using the put() and get() methods, just like you have always done:

Map<Integer, String> map = new HashMap<Integer, String>;

Integer key1   = new Integer(123);
String  value1 = "value 1";

map.put(key1, value1);

String value1_1 = map.get(key1);

So what is the big difference? Well, if you try to add a key, value pair that is not a Integer, String pair instance, to the Map in the example above, the compiler will complain. That's a pretty nice extra type check to have.

Also notice how it is not necessary to cast the String instance returned by the get() method. The compiler knows that this Map has String values, so casting is not necessary.

You can also use the new auto boxing features of Java 5 to make it easier to specify the Integer values, like this:

Map<Integer, String> map = new HashMap<Integer, String>;

Integer key1   = 123;
String  value1 = "value 1";

map.put(key1, value1);

//or

map.put(123, value1);


String value1_1 = map.get(123);

Iterating a Generic Map

A Map has two collections you can iterate. The key Set and the value Set. Most often you iterate the key Set and access the values for each key via the Map.get() method.

Here are two examples:

Map<Integer, String> map = new HashMap<Integer, String>;

//... add key, value pairs to the Map

// iterate keys.
Iterator<Integer> keyIterator   = map.keySet().iterator();

while(keyIterator.hasNext()){
  Integer aKey   = keyIterator.next();
  String  aValue = map.get(aKey);
}


Iterator<String>  valueIterator = map.values().iterator();

while(valueIterator.hasNext()){
  String aString = valueIterator.next();
}

Notice how it is not necessary to cast the object returned from the iterator.next() next call. Because the Map is generified (has a type), the compiler knows that it contains Integer instances for keys, and String instances for values. Therefore it is not necessary to cast the objects obtained from the Map, even if it comes from one of its Iterator's.

You can also use the new for-loop, like this:

Map<Integer, String> map = new HashMap<Integer, String>;

//... add key, value pairs to the Map

for(Integer aKey : map.keySet()) {
    String aValue = map.get(aKey);
    System.out.println("" + aKey + ":" + aValue);
}

for(String aValue : map.values()) {
    System.out.println(aValue);
}

Notice how an Integer and a String variable is declared inside the parantheses of each for-loop. For each iteration (each element in the Map's key set or value collection) this variable contains the current element (current Integer or String).

Jakob Jenkov




Copyright  Jenkov Aps
Close TOC