Creating Parameterized Types


You will develop a parameterized MultiHashMap. A MultiHashMap is similar to a HashMap, except that it allows you to associate multiple values with a given key. Let's expand on the calendar example: Some people lead particularly interesting lives, in which two events might occur on one day.

A few starter tests will get you off the ground. Remember that you should be developing incrementally, one test method and one assertion at a time.

 package sis.util; import junit.framework.*; import java.util.*; public class MultiHashMapTest extends TestCase {    private static final Date today = new Date();    private static final Date tomorrow =       new Date(today.getTime() + 86400000);    private static final String eventA = "wake up";    private static final String eventB = "eat";    private MultiHashMap<Date,String> events;    protected void setUp() {       events = new MultiHashMap<Date,String>();    }    public void testCreate() {       assertEquals(0, events.size());    }    public void testSingleEntry() {       events.put(today, eventA);       assertEquals(1, events.size());       assertEquals(eventA, getSoleEvent(today));    }    public void testMultipleEntriesDifferentKey() {       events.put(today, eventA);       events.put(tomorrow, eventB);       assertEquals(2, events.size());       assertEquals(eventA, getSoleEvent(today));       assertEquals(eventB, getSoleEvent(tomorrow));    }    public void testMultipleEntriesSameKey() {       events.put(today, eventA);       events.put(today, eventB);       assertEquals(1, events.size());       Collection<String> retrievedEvents = events.get(today);       assertEquals(2, retrievedEvents.size());       assertTrue(retrievedEvents.contains(eventA));       assertTrue(retrievedEvents.contains(eventB));    }    private String getSoleEvent(Date date) {       Collection<String> retrievedEvents = events.get(date);       assertEquals(1, retrievedEvents.size());       Iterator<String> it = retrievedEvents.iterator();       return it.next();    } } 

The method getSoleEvent is of some interest. After retrieving the events collection stored at a date using the Map method get, you must ensure that it contains only one element. To retrieve the sole element, you can create an iterator and return the first element it points to. You must bind the Iterator object to the same type that you bound the collection to (String in this example).

From an implementation standpoint, there is more than one way to build a MultiHashMap. The easiest is to use a HashMap where each key is associated with a collection of values. For this example, you will define MultiHashMap to encapsulate and use a HashMap.

In order to support the existing tests, the implementation of MultiHashMap is simplistic. Each method size, put, and get will delegate to the encapsulated HashMap:

 package sis.util; import java.util.*; public class MultiHashMap<K,V> {    private Map<K,List<V>> map = new HashMap<K,List<V>>();    public int size() {       return map.size();    }    public void put(K key, V value) {       List<V> values = map.get(key);       if (values == null) {          values = new ArrayList<V>();          map.put(key, values);       }       values.add(value);    }    public List<V> get(K key) {       return map.get(key);    } } 

The put method first extracts a list from map using the key passed in. If there is no entry at the key, the method constructs a new ArrayList bound to the value type V and puts this list into map. Regardless, value is added to the list.

Like HashMap, the type parameter list contains two type parameters, K and V. Throughout the definition for MultiHashMap, you will see these symbols where you might expect to see type names. For example, the get method returns V instead of, say, Object. Each use of a type parameter symbol within the type declaration is known as a naked type variable.

At compile time, each occurrence of a naked type variable is replaced with the appropriate type of the corresponding type parameter. You'll see how this actually works in the next section, Erasure.

In the definition of the map field (highlighted in bold), you construct a HashMap object and bind it to <K,List<V>>. The key for map is the same type and the one to which the key of MultiHashMap is bound (K). The value for map is a List bound to type Vthe value type to which the MultiHashMap is bound.

Bind parameters correspond to type parameters. The test contains this instantiation of MultiHashMap in its setUp method:

 events = new MultiHashMap<Date,String>(); 

The Date type corresponds to the type parameter K, and the String type corresponds to the type parameter V. Thus, the embedded map field would be a HashMap<Date,List<String>>a hash map whose key is bound to a date and whose value is bound to a list of strings.



Agile Java. Crafting Code with Test-Driven Development
Agile Javaв„ў: Crafting Code with Test-Driven Development
ISBN: 0131482394
EAN: 2147483647
Year: 2003
Pages: 391
Authors: Jeff Langr

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net