Common Java Cookbook

Edition: 0.19

Download PDF or Read on Scribd

Download Examples (ZIP)

5.10. Storing Multiple Values in a Map

5.10.1. Problem

You need to store multiple values for a single key in a Map. Instead of a one-to-one relationship between keys and values, you need a Map that provides one-to-many relationships between keys and values.

5.10.2. Solution

Use a MultiMap. A MultiMap maintains a collection of values for a given key. When a new key/value pair is added to a MultiMap, the value is added to the collection of values for that key. The MultiMap also provides a way to remove a specific key/value pair. The following example demonstrates the use of MultiMap:

import org.apache.commons.collections.MultiMap;
import org.apache.commons.collections.MultiHashMap;
MultiMap map = new MultiHashMap( );
map.put( "ONE", "TEST" );
map.put( "TWO", "PICNIC" );
map.put( "ONE", "HELLO" );
map.put( "TWO", "TESTIMONY" );
Set keySet = map.keySet( );
Iterator keyIterator = keySet.iterator( );
while( keyIterator.hasNext( ) ) {
    Object key = keyIterator.next( );
    System.out.print( "Key: " + key + ", " );
    Collection values = (Collection) map.get( key );
    Iterator valuesIterator = values.iterator( );
    while( valuesIterator.hasNext( ) ) {
        System.out.print( "Value: " + valuesIterator.next( ) + ". " );
    }
    System.out.print( "\n" );
}

Each key in a MultiMap corresponds to a collection of values. This example produces the following output while iterating through all values for each key:

Key: ONE, Value: TEST. Value: HELLO
Key: TWO, Value: PICNIC. Value: Testimony

5.10.3. Discussion

In a traditional Map, a key is removed with map.remove( ) ; this method removes the specified key from the map. In a MultiMap, a specific key/value pair can be removed from a key's value collection. When removing a specific pair, the value is extracted from a key's value collection. Example 5-10 demonstrates the use of a MultiMap.remove() method.

Example 5-10. Using MultiMap.remove( )

package com.discursive.jccook.collections.map;
import org.apache.commons.collections.*;
import java.util.*;
public class MultiMapExample {
    public static void main(String[] args) {
        MultiMapExample example = new MultiMapExample( );
        example.start( );
    }
    public void start( ) {
        MultiMap map = new MultiHashMap( );
        map.put( "ONE", "TEST" );
        map.put( "ONE", "WAR" );
        map.put( "ONE", "CAR" );
        map.put( "ONE", "WEST" );
        map.put( "TWO", "SKY" );
        map.put( "TWO", "WEST" );
        map.put( "TWO", "SCHOOL" );
        // At this point "ONE" should correspond to "TEST", "WAR", "CAR", "WEST"
        map.remove( "ONE", "WAR" );
        map.remove( "ONE", "CAR" );
        // The size of this collection should be two "TEST", "WEST"
        Collection oneCollection = (Collection) map.get("ONE");
        // This collection should be "TEST", "WEST", "SKY", "WEST", "SCHOOL"
        Collection values = map.values( );
    }
}

The MultiMap is relevant when one object is associated with many different objects. A sensible example would be a MultiMap of people to the languages they speak fluently, and the following example demonstrates such a Map:

MultiMap languageAbility = new MultiHashMap( );
languageAbility.put( "Tom", "French" );
languageAbility.put( "Chris", "Spanish" );
languageAbility.put( "Chris", "German" );
languageAbility.put( "John", "Arabic" );
languageAbility.put( "Tom", "Pashto" );
// What languages does Tom speak?
Collection languages = (Collection) languageAbility.get("Tom");
Iterator languageIterator = languages.iterator( );
while( languageIterator.hasNext( ) ) {
    System.out.println( "Tom speaks " + languageIterator.next( ) );
}

If you had to locate people who were fluent in a given language, it would be equally as valid to use languages as keys and names as values. One could then query the MultiMap for a list of people who speak a certain language. If your system contains two collections of objects that have a many-to-many relationship, these relationships can be managed with two instances of MultiMap.


Creative Commons License
Common Java Cookbook by Tim O'Brien is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 United States License.
Permissions beyond the scope of this license may be available at http://www.discursive.com/books/cjcook/reference/jakartackbk-PREFACE-1.html. Copyright 2009. Common Java Cookbook Chunked HTML Output. Some Rights Reserved.