You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ch...@apache.org on 2017/07/11 17:55:05 UTC

[20/77] [abbrv] commons-collections git commit: finish generics (minus one class)

http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/ListOrderedMap.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/commons/collections/map/ListOrderedMap.java b/src/java/org/apache/commons/collections/map/ListOrderedMap.java
index e27f914..c94f907 100644
--- a/src/java/org/apache/commons/collections/map/ListOrderedMap.java
+++ b/src/java/org/apache/commons/collections/map/ListOrderedMap.java
@@ -32,11 +32,10 @@ import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Set;
 
-import org.apache.commons.collections.MapIterator;
 import org.apache.commons.collections.OrderedMap;
 import org.apache.commons.collections.OrderedMapIterator;
 import org.apache.commons.collections.ResettableIterator;
-import org.apache.commons.collections.iterators.AbstractIteratorDecorator;
+import org.apache.commons.collections.iterators.AbstractUntypedIteratorDecorator;
 import org.apache.commons.collections.keyvalue.AbstractMapEntry;
 import org.apache.commons.collections.list.UnmodifiableList;
 
@@ -68,15 +67,15 @@ import org.apache.commons.collections.list.UnmodifiableList;
  * @author Stephen Colebourne
  * @author Matt Benson
  */
-public class ListOrderedMap
-        extends AbstractMapDecorator
-        implements OrderedMap, Serializable {
+public class ListOrderedMap<K, V>
+        extends AbstractMapDecorator<K, V>
+        implements OrderedMap<K, V>, Serializable {
 
     /** Serialization version */
     private static final long serialVersionUID = 2728177751851003750L;
 
     /** Internal list to hold the sequence of objects */
-    protected final List insertOrder = new ArrayList();
+    protected final List<K> insertOrder = new ArrayList<K>();
 
     /**
      * Factory method to create an ordered map.
@@ -86,8 +85,8 @@ public class ListOrderedMap
      * @param map  the map to decorate, must not be null
      * @throws IllegalArgumentException if map is null
      */
-    public static OrderedMap decorate(Map map) {
-        return new ListOrderedMap(map);
+    public static <K, V> OrderedMap<K, V> decorate(Map<K, V> map) {
+        return new ListOrderedMap<K, V>(map);
     }
 
     //-----------------------------------------------------------------------
@@ -98,7 +97,7 @@ public class ListOrderedMap
      * @since Commons Collections 3.1
      */
     public ListOrderedMap() {
-        this(new HashMap());
+        this(new HashMap<K, V>());
     }
 
     /**
@@ -107,7 +106,7 @@ public class ListOrderedMap
      * @param map  the map to decorate, must not be null
      * @throws IllegalArgumentException if map is null
      */
-    protected ListOrderedMap(Map map) {
+    protected ListOrderedMap(Map<K, V> map) {
         super(map);
         insertOrder.addAll(decorated().keySet());
     }
@@ -133,6 +132,7 @@ public class ListOrderedMap
      * @throws ClassNotFoundException
      * @since Commons Collections 3.1
      */
+    @SuppressWarnings("unchecked")
     private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
         in.defaultReadObject();
         map = (Map) in.readObject();
@@ -140,12 +140,8 @@ public class ListOrderedMap
 
     // Implement OrderedMap
     //-----------------------------------------------------------------------
-    public MapIterator mapIterator() {
-        return orderedMapIterator();
-    }
-
-    public OrderedMapIterator orderedMapIterator() {
-        return new ListOrderedMapIterator(this);
+    public OrderedMapIterator<K, V> mapIterator() {
+        return new ListOrderedMapIterator<K, V>(this);
     }
 
     /**
@@ -154,7 +150,7 @@ public class ListOrderedMap
      * @return the first key currently in this map
      * @throws NoSuchElementException if this map is empty
      */
-    public Object firstKey() {
+    public K firstKey() {
         if (size() == 0) {
             throw new NoSuchElementException("Map is empty");
         }
@@ -167,7 +163,7 @@ public class ListOrderedMap
      * @return the last key currently in this map
      * @throws NoSuchElementException if this map is empty
      */
-    public Object lastKey() {
+    public K lastKey() {
         if (size() == 0) {
             throw new NoSuchElementException("Map is empty");
         }
@@ -181,7 +177,7 @@ public class ListOrderedMap
      * @param key  the key to find previous for
      * @return the next key, null if no match or at start
      */
-    public Object nextKey(Object key) {
+    public K nextKey(Object key) {
         int index = insertOrder.indexOf(key);
         if (index >= 0 && index < size() - 1) {
             return insertOrder.get(index + 1);
@@ -196,7 +192,7 @@ public class ListOrderedMap
      * @param key  the key to find previous for
      * @return the previous key, null if no match or at start
      */
-    public Object previousKey(Object key) {
+    public K previousKey(Object key) {
         int index = insertOrder.indexOf(key);
         if (index > 0) {
             return insertOrder.get(index - 1);
@@ -205,27 +201,26 @@ public class ListOrderedMap
     }
 
     //-----------------------------------------------------------------------
-    public Object put(Object key, Object value) {
+    public V put(K key, V value) {
         if (decorated().containsKey(key)) {
             // re-adding doesn't change order
             return decorated().put(key, value);
         } else {
             // first add, so add to both map and list
-            Object result = decorated().put(key, value);
+            V result = decorated().put(key, value);
             insertOrder.add(key);
             return result;
         }
     }
 
-    public void putAll(Map map) {
-        for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
-            Map.Entry entry = (Map.Entry) it.next();
+    public void putAll(Map<? extends K, ? extends V> map) {
+        for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
             put(entry.getKey(), entry.getValue());
         }
     }
 
-    public Object remove(Object key) {
-        Object result = decorated().remove(key);
+    public V remove(Object key) {
+        V result = decorated().remove(key);
         insertOrder.remove(key);
         return result;
     }
@@ -244,8 +239,8 @@ public class ListOrderedMap
      * @see #keyList()
      * @return the fully modifiable collection view over the keys
      */
-    public Set keySet() {
-        return new KeySetView(this);
+    public Set<K> keySet() {
+        return new KeySetView<K>(this);
     }
 
     /**
@@ -258,7 +253,7 @@ public class ListOrderedMap
      * @return the unmodifiable list view over the keys
      * @since Commons Collections 3.2
      */
-    public List keyList() {
+    public List<K> keyList() {
         return UnmodifiableList.decorate(insertOrder);
     }
 
@@ -273,8 +268,8 @@ public class ListOrderedMap
      * @see #valueList()
      * @return the fully modifiable collection view over the values
      */
-    public Collection values() {
-        return new ValuesView(this);
+    public Collection<V> values() {
+        return new ValuesView<V>(this);
     }
 
     /**
@@ -287,8 +282,8 @@ public class ListOrderedMap
      * @return the partially modifiable list view over the values
      * @since Commons Collections 3.2
      */
-    public List valueList() {
-        return new ValuesView(this);
+    public List<V> valueList() {
+        return new ValuesView<V>(this);
     }
 
     /**
@@ -298,8 +293,8 @@ public class ListOrderedMap
      *
      * @return the fully modifiable set view over the entries
      */
-    public Set entrySet() {
-        return new EntrySetView(this, this.insertOrder);
+    public Set<Map.Entry<K, V>> entrySet() {
+        return new EntrySetView<K, V>(this, this.insertOrder);
     }
 
     //-----------------------------------------------------------------------
@@ -315,11 +310,9 @@ public class ListOrderedMap
         StringBuffer buf = new StringBuffer();
         buf.append('{');
         boolean first = true;
-        Iterator it = entrySet().iterator();
-        while (it.hasNext()) {
-            Map.Entry entry = (Map.Entry) it.next();
-            Object key = entry.getKey();
-            Object value = entry.getValue();
+        for (Map.Entry<K, V> entry : entrySet()) {
+            K key = entry.getKey();
+            V value = entry.getValue();
             if (first) {
                 first = false;
             } else {
@@ -341,7 +334,7 @@ public class ListOrderedMap
      * @return the key at the specified index
      * @throws IndexOutOfBoundsException if the index is invalid
      */
-    public Object get(int index) {
+    public K get(int index) {
         return insertOrder.get(index);
     }
     
@@ -352,7 +345,7 @@ public class ListOrderedMap
      * @return the key at the specified index
      * @throws IndexOutOfBoundsException if the index is invalid
      */
-    public Object getValue(int index) {
+    public V getValue(int index) {
         return get(insertOrder.get(index));
     }
     
@@ -374,8 +367,8 @@ public class ListOrderedMap
      * @throws IndexOutOfBoundsException if the index is invalid
      * @since Commons Collections 3.2
      */
-    public Object setValue(int index, Object value) {
-        Object key = insertOrder.get(index);
+    public V setValue(int index, V value) {
+        K key = insertOrder.get(index);
         return put(key, value);
     }
 
@@ -398,10 +391,10 @@ public class ListOrderedMap
      * @throws IndexOutOfBoundsException if the index is out of range
      * @since Commons Collections 3.2
      */
-    public Object put(int index, Object key, Object value) {
-        Map m = decorated();
+    public V put(int index, K key, V value) {
+        Map<K, V> m = decorated();
         if (m.containsKey(key)) {
-            Object result = m.remove(key);
+            V result = m.remove(key);
             int pos = insertOrder.indexOf(key);
             insertOrder.remove(pos);
             if (pos < index) {
@@ -424,7 +417,7 @@ public class ListOrderedMap
      * @return the removed value, or <code>null</code> if none existed
      * @throws IndexOutOfBoundsException if the index is invalid
      */
-    public Object remove(int index) {
+    public V remove(int index) {
         return remove(get(index));
     }
 
@@ -445,17 +438,18 @@ public class ListOrderedMap
      * @see #keySet()
      * @return The ordered list of keys.  
      */
-    public List asList() {
+    public List<K> asList() {
         return keyList();
     }
 
     //-----------------------------------------------------------------------
-    static class ValuesView extends AbstractList {
-        private final ListOrderedMap parent;
+    static class ValuesView<V> extends AbstractList<V> {
+        private final ListOrderedMap<Object, V> parent;
 
-        ValuesView(ListOrderedMap parent) {
+        @SuppressWarnings("unchecked")
+        ValuesView(ListOrderedMap<?, V> parent) {
             super();
-            this.parent = parent;
+            this.parent = (ListOrderedMap<Object, V>) parent;
         }
 
         public int size() {
@@ -470,34 +464,35 @@ public class ListOrderedMap
             this.parent.clear();
         }
 
-        public Iterator iterator() {
-            return new AbstractIteratorDecorator(parent.entrySet().iterator()) {
-                public Object next() {
-                    return ((Map.Entry) iterator.next()).getValue();
+        public Iterator<V> iterator() {
+            return new AbstractUntypedIteratorDecorator<Map.Entry<Object, V>, V>(parent.entrySet().iterator()) {
+                public V next() {
+                    return getIterator().next().getValue();
                 }
             };
         }
 
-        public Object get(int index) {
+        public V get(int index) {
             return this.parent.getValue(index);
         }
 
-        public Object set(int index, Object value) {
+        public V set(int index, V value) {
             return this.parent.setValue(index, value);
         }
 
-        public Object remove(int index) {
+        public V remove(int index) {
             return this.parent.remove(index);
         }
     }
 
     //-----------------------------------------------------------------------
-    static class KeySetView extends AbstractSet {
-        private final ListOrderedMap parent;
+    static class KeySetView<K> extends AbstractSet<K> {
+        private final ListOrderedMap<K, Object> parent;
 
-        KeySetView(ListOrderedMap parent) {
+        @SuppressWarnings("unchecked")
+        KeySetView(ListOrderedMap<K, ?> parent) {
             super();
-            this.parent = parent;
+            this.parent = (ListOrderedMap<K, Object>) parent;
         }
 
         public int size() {
@@ -512,28 +507,28 @@ public class ListOrderedMap
             this.parent.clear();
         }
 
-        public Iterator iterator() {
-            return new AbstractIteratorDecorator(parent.entrySet().iterator()) {
-                public Object next() {
-                    return ((Map.Entry) super.next()).getKey();
+        public Iterator<K> iterator() {
+            return new AbstractUntypedIteratorDecorator<Map.Entry<K, Object>, K>(parent.entrySet().iterator()) {
+                public K next() {
+                    return getIterator().next().getKey();
                 }
             };
         }
     }
 
     //-----------------------------------------------------------------------    
-    static class EntrySetView extends AbstractSet {
-        private final ListOrderedMap parent;
-        private final List insertOrder;
-        private Set entrySet;
+    static class EntrySetView<K, V> extends AbstractSet<Map.Entry<K, V>> {
+        private final ListOrderedMap<K, V> parent;
+        private final List<K> insertOrder;
+        private Set<Map.Entry<K, V>> entrySet;
 
-        public EntrySetView(ListOrderedMap parent, List insertOrder) {
+        public EntrySetView(ListOrderedMap<K, V> parent, List<K> insertOrder) {
             super();
             this.parent = parent;
             this.insertOrder = insertOrder;
         }
 
-        private Set getEntrySet() {
+        private Set<Map.Entry<K, V>> getEntrySet() {
             if (entrySet == null) {
                 entrySet = parent.decorated().entrySet();
             }
@@ -551,16 +546,17 @@ public class ListOrderedMap
             return getEntrySet().contains(obj);
         }
 
-        public boolean containsAll(Collection coll) {
+        public boolean containsAll(Collection<?> coll) {
             return getEntrySet().containsAll(coll);
         }
 
+        @SuppressWarnings("unchecked")
         public boolean remove(Object obj) {
             if (obj instanceof Map.Entry == false) {
                 return false;
             }
             if (getEntrySet().contains(obj)) {
-                Object key = ((Map.Entry) obj).getKey();
+                Object key = ((Map.Entry<K, V>) obj).getKey();
                 parent.remove(key);
                 return true;
             }
@@ -570,14 +566,14 @@ public class ListOrderedMap
         public void clear() {
             this.parent.clear();
         }
-        
+
         public boolean equals(Object obj) {
             if (obj == this) {
                 return true;
             }
             return getEntrySet().equals(obj);
         }
-        
+
         public int hashCode() {
             return getEntrySet().hashCode();
         }
@@ -585,25 +581,25 @@ public class ListOrderedMap
         public String toString() {
             return getEntrySet().toString();
         }
-        
-        public Iterator iterator() {
-            return new ListOrderedIterator(parent, insertOrder);
+
+        public Iterator<Map.Entry<K, V>> iterator() {
+            return new ListOrderedIterator<K, V>(parent, insertOrder);
         }
     }
-    
+
     //-----------------------------------------------------------------------
-    static class ListOrderedIterator extends AbstractIteratorDecorator {
-        private final ListOrderedMap parent;
-        private Object last = null;
+    static class ListOrderedIterator<K, V> extends AbstractUntypedIteratorDecorator<K, Map.Entry<K, V>> {
+        private final ListOrderedMap<K, V> parent;
+        private K last = null;
         
-        ListOrderedIterator(ListOrderedMap parent, List insertOrder) {
+        ListOrderedIterator(ListOrderedMap<K, V> parent, List<K> insertOrder) {
             super(insertOrder.iterator());
             this.parent = parent;
         }
-        
-        public Object next() {
-            last = super.next();
-            return new ListOrderedMapEntry(parent, last);
+
+        public Map.Entry<K, V> next() {
+            last = getIterator().next();
+            return new ListOrderedMapEntry<K, V>(parent, last);
         }
 
         public void remove() {
@@ -611,43 +607,43 @@ public class ListOrderedMap
             parent.decorated().remove(last);
         }
     }
-    
+
     //-----------------------------------------------------------------------
-    static class ListOrderedMapEntry extends AbstractMapEntry {
-        private final ListOrderedMap parent;
-        
-        ListOrderedMapEntry(ListOrderedMap parent, Object key) {
+    static class ListOrderedMapEntry<K, V> extends AbstractMapEntry<K, V> {
+        private final ListOrderedMap<K, V> parent;
+
+        ListOrderedMapEntry(ListOrderedMap<K, V> parent, K key) {
             super(key, null);
             this.parent = parent;
         }
-        
-        public Object getValue() {
+
+        public V getValue() {
             return parent.get(key);
         }
 
-        public Object setValue(Object value) {
+        public V setValue(V value) {
             return parent.decorated().put(key, value);
         }
     }
 
     //-----------------------------------------------------------------------
-    static class ListOrderedMapIterator implements OrderedMapIterator, ResettableIterator {
-        private final ListOrderedMap parent;
-        private ListIterator iterator;
-        private Object last = null;
+    static class ListOrderedMapIterator<K, V> implements OrderedMapIterator<K, V>, ResettableIterator<K> {
+        private final ListOrderedMap<K, V> parent;
+        private ListIterator<K> iterator;
+        private K last = null;
         private boolean readable = false;
-        
-        ListOrderedMapIterator(ListOrderedMap parent) {
+
+        ListOrderedMapIterator(ListOrderedMap<K, V> parent) {
             super();
             this.parent = parent;
             this.iterator = parent.insertOrder.listIterator();
         }
-        
+
         public boolean hasNext() {
             return iterator.hasNext();
         }
-        
-        public Object next() {
+
+        public K next() {
             last = iterator.next();
             readable = true;
             return last;
@@ -656,13 +652,13 @@ public class ListOrderedMap
         public boolean hasPrevious() {
             return iterator.hasPrevious();
         }
-        
-        public Object previous() {
+
+        public K previous() {
             last = iterator.previous();
             readable = true;
             return last;
         }
-        
+
         public void remove() {
             if (readable == false) {
                 throw new IllegalStateException(AbstractHashedMap.REMOVE_INVALID);
@@ -671,41 +667,40 @@ public class ListOrderedMap
             parent.map.remove(last);
             readable = false;
         }
-        
-        public Object getKey() {
+
+        public K getKey() {
             if (readable == false) {
                 throw new IllegalStateException(AbstractHashedMap.GETKEY_INVALID);
             }
             return last;
         }
 
-        public Object getValue() {
+        public V getValue() {
             if (readable == false) {
                 throw new IllegalStateException(AbstractHashedMap.GETVALUE_INVALID);
             }
             return parent.get(last);
         }
-        
-        public Object setValue(Object value) {
+
+        public V setValue(V value) {
             if (readable == false) {
                 throw new IllegalStateException(AbstractHashedMap.SETVALUE_INVALID);
             }
             return parent.map.put(last, value);
         }
-        
+
         public void reset() {
             iterator = parent.insertOrder.listIterator();
             last = null;
             readable = false;
         }
-        
+
         public String toString() {
             if (readable == true) {
                 return "Iterator[" + getKey() + "=" + getValue() + "]";
-            } else {
-                return "Iterator[]";
             }
+            return "Iterator[]";
         }
     }
-    
+
 }

http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/MultiKeyMap.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/commons/collections/map/MultiKeyMap.java b/src/java/org/apache/commons/collections/map/MultiKeyMap.java
index b8af692..563e7bd 100644
--- a/src/java/org/apache/commons/collections/map/MultiKeyMap.java
+++ b/src/java/org/apache/commons/collections/map/MultiKeyMap.java
@@ -17,10 +17,7 @@
 package org.apache.commons.collections.map;
 
 import java.io.Serializable;
-import java.util.Collection;
-import java.util.Iterator;
 import java.util.Map;
-import java.util.Set;
 
 import org.apache.commons.collections.IterableMap;
 import org.apache.commons.collections.MapIterator;
@@ -77,14 +74,15 @@ import org.apache.commons.collections.keyvalue.MultiKey;
  *
  * @author Stephen Colebourne
  */
-public class MultiKeyMap
-        implements IterableMap, Serializable {
+public class MultiKeyMap<K, V> extends AbstractMapDecorator<MultiKey<? extends K>, V>
+        implements IterableMap<MultiKey<? extends K>, V>, Serializable {
 
     /** Serialisation version */
     private static final long serialVersionUID = -1788199231038721040L;
 
     /** The decorated map */
-    protected final AbstractHashedMap map;
+    //keep this member around for serialization BC with older Collections releases assuming we want to do that
+    protected AbstractHashedMap<MultiKey<? extends K>, V> map;
 
     //-----------------------------------------------------------------------
     /**
@@ -94,14 +92,14 @@ public class MultiKeyMap
      * @param map  the map to decorate, not null
      * @throws IllegalArgumentException if the map is null or not empty
      */
-    public static MultiKeyMap decorate(AbstractHashedMap map) {
+    public static <K, V> MultiKeyMap<K, V> decorate(AbstractHashedMap<MultiKey<? extends K>, V> map) {
         if (map == null) {
             throw new IllegalArgumentException("Map must not be null");
         }
         if (map.size() > 0) {
             throw new IllegalArgumentException("Map must be empty");
         }
-        return new MultiKeyMap(map);
+        return new MultiKeyMap<K, V>(map);
     }
 
     //-----------------------------------------------------------------------    
@@ -109,8 +107,7 @@ public class MultiKeyMap
      * Constructs a new MultiKeyMap that decorates a <code>HashedMap</code>.
      */
     public MultiKeyMap() {
-        super();
-        map = new HashedMap();
+        this(new HashedMap<MultiKey<? extends K>, V>());
     }
 
     /**
@@ -121,8 +118,8 @@ public class MultiKeyMap
      *
      * @param map  the map to decorate
      */
-    protected MultiKeyMap(AbstractHashedMap map) {
-        super();
+    protected MultiKeyMap(AbstractHashedMap<MultiKey<? extends K>, V> map) {
+        super(map);
         this.map = map;
     }
 
@@ -134,9 +131,9 @@ public class MultiKeyMap
      * @param key2  the second key
      * @return the mapped value, null if no match
      */
-    public Object get(Object key1, Object key2) {
+    public V get(Object key1, Object key2) {
         int hashCode = hash(key1, key2);
-        AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)];
+        AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[decorated().hashIndex(hashCode, decorated().data.length)];
         while (entry != null) {
             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2)) {
                 return entry.getValue();
@@ -155,7 +152,7 @@ public class MultiKeyMap
      */
     public boolean containsKey(Object key1, Object key2) {
         int hashCode = hash(key1, key2);
-        AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)];
+        AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[decorated().hashIndex(hashCode, decorated().data.length)];
         while (entry != null) {
             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2)) {
                 return true;
@@ -173,20 +170,19 @@ public class MultiKeyMap
      * @param value  the value to store
      * @return the value previously mapped to this combined key, null if none
      */
-    public Object put(Object key1, Object key2, Object value) {
+    public V put(K key1, K key2, V value) {
         int hashCode = hash(key1, key2);
-        int index = map.hashIndex(hashCode, map.data.length);
-        AbstractHashedMap.HashEntry entry = map.data[index];
+        int index = decorated().hashIndex(hashCode, decorated().data.length);
+        AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[index];
         while (entry != null) {
             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2)) {
-                Object oldValue = entry.getValue();
-                map.updateEntry(entry, value);
+                V oldValue = entry.getValue();
+                decorated().updateEntry(entry, value);
                 return oldValue;
             }
             entry = entry.next;
         }
-        
-        map.addMapping(index, hashCode, new MultiKey(key1, key2), value);
+        decorated().addMapping(index, hashCode, new MultiKey<K>(key1, key2), value);
         return null;
     }
 
@@ -197,15 +193,15 @@ public class MultiKeyMap
      * @param key2  the second key
      * @return the value mapped to the removed key, null if key not in map
      */
-    public Object remove(Object key1, Object key2) {
+    public V remove(Object key1, Object key2) {
         int hashCode = hash(key1, key2);
-        int index = map.hashIndex(hashCode, map.data.length);
-        AbstractHashedMap.HashEntry entry = map.data[index];
-        AbstractHashedMap.HashEntry previous = null;
+        int index = decorated().hashIndex(hashCode, decorated().data.length);
+        AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[index];
+        AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> previous = null;
         while (entry != null) {
             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2)) {
-                Object oldValue = entry.getValue();
-                map.removeMapping(entry, index, previous);
+                V oldValue = entry.getValue();
+                decorated().removeMapping(entry, index, previous);
                 return oldValue;
             }
             previous = entry;
@@ -244,12 +240,13 @@ public class MultiKeyMap
      * @param key2  the second key
      * @return true if the key matches
      */
-    protected boolean isEqualKey(AbstractHashedMap.HashEntry entry, Object key1, Object key2) {
-        MultiKey multi = (MultiKey) entry.getKey();
+    protected boolean isEqualKey(AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry,
+            Object key1, Object key2) {
+        MultiKey<? extends K> multi = entry.getKey();
         return
             multi.size() == 2 &&
-            (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) &&
-            (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1)));
+            (key1 == multi.getKey(0) || key1 != null && key1.equals(multi.getKey(0))) &&
+            (key2 == multi.getKey(1) || key1 != null && key2.equals(multi.getKey(1)));
     }
 
     //-----------------------------------------------------------------------
@@ -261,9 +258,9 @@ public class MultiKeyMap
      * @param key3  the third key
      * @return the mapped value, null if no match
      */
-    public Object get(Object key1, Object key2, Object key3) {
+    public V get(Object key1, Object key2, Object key3) {
         int hashCode = hash(key1, key2, key3);
-        AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)];
+        AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[decorated().hashIndex(hashCode, decorated().data.length)];
         while (entry != null) {
             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3)) {
                 return entry.getValue();
@@ -283,7 +280,7 @@ public class MultiKeyMap
      */
     public boolean containsKey(Object key1, Object key2, Object key3) {
         int hashCode = hash(key1, key2, key3);
-        AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)];
+        AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[decorated().hashIndex(hashCode, decorated().data.length)];
         while (entry != null) {
             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3)) {
                 return true;
@@ -302,20 +299,19 @@ public class MultiKeyMap
      * @param value  the value to store
      * @return the value previously mapped to this combined key, null if none
      */
-    public Object put(Object key1, Object key2, Object key3, Object value) {
+    public V put(K key1, K key2, K key3, V value) {
         int hashCode = hash(key1, key2, key3);
-        int index = map.hashIndex(hashCode, map.data.length);
-        AbstractHashedMap.HashEntry entry = map.data[index];
+        int index = decorated().hashIndex(hashCode, decorated().data.length);
+        AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[index];
         while (entry != null) {
             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3)) {
-                Object oldValue = entry.getValue();
-                map.updateEntry(entry, value);
+                V oldValue = entry.getValue();
+                decorated().updateEntry(entry, value);
                 return oldValue;
             }
             entry = entry.next;
         }
-        
-        map.addMapping(index, hashCode, new MultiKey(key1, key2, key3), value);
+        decorated().addMapping(index, hashCode, new MultiKey<K>(key1, key2, key3), value);
         return null;
     }
 
@@ -327,15 +323,15 @@ public class MultiKeyMap
      * @param key3  the third key
      * @return the value mapped to the removed key, null if key not in map
      */
-    public Object remove(Object key1, Object key2, Object key3) {
+    public V remove(Object key1, Object key2, Object key3) {
         int hashCode = hash(key1, key2, key3);
-        int index = map.hashIndex(hashCode, map.data.length);
-        AbstractHashedMap.HashEntry entry = map.data[index];
-        AbstractHashedMap.HashEntry previous = null;
+        int index = decorated().hashIndex(hashCode, decorated().data.length);
+        AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[index];
+        AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> previous = null;
         while (entry != null) {
             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3)) {
-                Object oldValue = entry.getValue();
-                map.removeMapping(entry, index, previous);
+                V oldValue = entry.getValue();
+                decorated().removeMapping(entry, index, previous);
                 return oldValue;
             }
             previous = entry;
@@ -379,13 +375,13 @@ public class MultiKeyMap
      * @param key3  the third key
      * @return true if the key matches
      */
-    protected boolean isEqualKey(AbstractHashedMap.HashEntry entry, Object key1, Object key2, Object key3) {
-        MultiKey multi = (MultiKey) entry.getKey();
+    protected boolean isEqualKey(AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry, Object key1, Object key2, Object key3) {
+        MultiKey<? extends K> multi = entry.getKey();
         return
             multi.size() == 3 &&
-            (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) &&
-            (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1))) &&
-            (key3 == null ? multi.getKey(2) == null : key3.equals(multi.getKey(2)));
+            (key1 == multi.getKey(0) || key1 != null && key1.equals(multi.getKey(0))) &&
+            (key2 == multi.getKey(1) || key2 != null && key2.equals(multi.getKey(1))) &&
+            (key3 == multi.getKey(2) || key3 != null && key3.equals(multi.getKey(2)));
     }
 
     //-----------------------------------------------------------------------
@@ -398,9 +394,9 @@ public class MultiKeyMap
      * @param key4  the fourth key
      * @return the mapped value, null if no match
      */
-    public Object get(Object key1, Object key2, Object key3, Object key4) {
+    public V get(Object key1, Object key2, Object key3, Object key4) {
         int hashCode = hash(key1, key2, key3, key4);
-        AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)];
+        AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[decorated().hashIndex(hashCode, decorated().data.length)];
         while (entry != null) {
             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4)) {
                 return entry.getValue();
@@ -421,7 +417,7 @@ public class MultiKeyMap
      */
     public boolean containsKey(Object key1, Object key2, Object key3, Object key4) {
         int hashCode = hash(key1, key2, key3, key4);
-        AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)];
+        AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[decorated().hashIndex(hashCode, decorated().data.length)];
         while (entry != null) {
             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4)) {
                 return true;
@@ -441,20 +437,19 @@ public class MultiKeyMap
      * @param value  the value to store
      * @return the value previously mapped to this combined key, null if none
      */
-    public Object put(Object key1, Object key2, Object key3, Object key4, Object value) {
+    public V put(K key1, K key2, K key3, K key4, V value) {
         int hashCode = hash(key1, key2, key3, key4);
-        int index = map.hashIndex(hashCode, map.data.length);
-        AbstractHashedMap.HashEntry entry = map.data[index];
+        int index = decorated().hashIndex(hashCode, decorated().data.length);
+        AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[index];
         while (entry != null) {
             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4)) {
-                Object oldValue = entry.getValue();
-                map.updateEntry(entry, value);
+                V oldValue = entry.getValue();
+                decorated().updateEntry(entry, value);
                 return oldValue;
             }
             entry = entry.next;
         }
-        
-        map.addMapping(index, hashCode, new MultiKey(key1, key2, key3, key4), value);
+        decorated().addMapping(index, hashCode, new MultiKey<K>(key1, key2, key3, key4), value);
         return null;
     }
 
@@ -467,15 +462,15 @@ public class MultiKeyMap
      * @param key4  the fourth key
      * @return the value mapped to the removed key, null if key not in map
      */
-    public Object remove(Object key1, Object key2, Object key3, Object key4) {
+    public V remove(Object key1, Object key2, Object key3, Object key4) {
         int hashCode = hash(key1, key2, key3, key4);
-        int index = map.hashIndex(hashCode, map.data.length);
-        AbstractHashedMap.HashEntry entry = map.data[index];
-        AbstractHashedMap.HashEntry previous = null;
+        int index = decorated().hashIndex(hashCode, decorated().data.length);
+        AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[index];
+        AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> previous = null;
         while (entry != null) {
             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4)) {
-                Object oldValue = entry.getValue();
-                map.removeMapping(entry, index, previous);
+                V oldValue = entry.getValue();
+                decorated().removeMapping(entry, index, previous);
                 return oldValue;
             }
             previous = entry;
@@ -524,14 +519,14 @@ public class MultiKeyMap
      * @param key4  the fourth key
      * @return true if the key matches
      */
-    protected boolean isEqualKey(AbstractHashedMap.HashEntry entry, Object key1, Object key2, Object key3, Object key4) {
-        MultiKey multi = (MultiKey) entry.getKey();
+    protected boolean isEqualKey(AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry, Object key1, Object key2, Object key3, Object key4) {
+        MultiKey<? extends K> multi = entry.getKey();
         return
             multi.size() == 4 &&
-            (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) &&
-            (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1))) &&
-            (key3 == null ? multi.getKey(2) == null : key3.equals(multi.getKey(2))) &&
-            (key4 == null ? multi.getKey(3) == null : key4.equals(multi.getKey(3)));
+            (key1 == multi.getKey(0) || key1 != null && key1.equals(multi.getKey(0))) &&
+            (key2 == multi.getKey(1) || key2 != null && key2.equals(multi.getKey(1))) &&
+            (key3 == multi.getKey(2) || key3 != null && key3.equals(multi.getKey(2))) &&
+            (key4 == multi.getKey(3) || key4 != null && key4.equals(multi.getKey(3)));
     }
 
     //-----------------------------------------------------------------------
@@ -545,9 +540,9 @@ public class MultiKeyMap
      * @param key5  the fifth key
      * @return the mapped value, null if no match
      */
-    public Object get(Object key1, Object key2, Object key3, Object key4, Object key5) {
+    public V get(Object key1, Object key2, Object key3, Object key4, Object key5) {
         int hashCode = hash(key1, key2, key3, key4, key5);
-        AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)];
+        AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[decorated().hashIndex(hashCode, decorated().data.length)];
         while (entry != null) {
             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4, key5)) {
                 return entry.getValue();
@@ -569,7 +564,7 @@ public class MultiKeyMap
      */
     public boolean containsKey(Object key1, Object key2, Object key3, Object key4, Object key5) {
         int hashCode = hash(key1, key2, key3, key4, key5);
-        AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)];
+        AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[decorated().hashIndex(hashCode, decorated().data.length)];
         while (entry != null) {
             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4, key5)) {
                 return true;
@@ -590,20 +585,19 @@ public class MultiKeyMap
      * @param value  the value to store
      * @return the value previously mapped to this combined key, null if none
      */
-    public Object put(Object key1, Object key2, Object key3, Object key4, Object key5, Object value) {
+    public V put(K key1, K key2, K key3, K key4, K key5, V value) {
         int hashCode = hash(key1, key2, key3, key4, key5);
-        int index = map.hashIndex(hashCode, map.data.length);
-        AbstractHashedMap.HashEntry entry = map.data[index];
+        int index = decorated().hashIndex(hashCode, decorated().data.length);
+        AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[index];
         while (entry != null) {
             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4, key5)) {
-                Object oldValue = entry.getValue();
-                map.updateEntry(entry, value);
+                V oldValue = entry.getValue();
+                decorated().updateEntry(entry, value);
                 return oldValue;
             }
             entry = entry.next;
         }
-        
-        map.addMapping(index, hashCode, new MultiKey(key1, key2, key3, key4, key5), value);
+        decorated().addMapping(index, hashCode, new MultiKey<K>(key1, key2, key3, key4, key5), value);
         return null;
     }
 
@@ -617,15 +611,15 @@ public class MultiKeyMap
      * @param key5  the fifth key
      * @return the value mapped to the removed key, null if key not in map
      */
-    public Object remove(Object key1, Object key2, Object key3, Object key4, Object key5) {
+    public V remove(Object key1, Object key2, Object key3, Object key4, Object key5) {
         int hashCode = hash(key1, key2, key3, key4, key5);
-        int index = map.hashIndex(hashCode, map.data.length);
-        AbstractHashedMap.HashEntry entry = map.data[index];
-        AbstractHashedMap.HashEntry previous = null;
+        int index = decorated().hashIndex(hashCode, decorated().data.length);
+        AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[index];
+        AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> previous = null;
         while (entry != null) {
             if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4, key5)) {
-                Object oldValue = entry.getValue();
-                map.removeMapping(entry, index, previous);
+                V oldValue = entry.getValue();
+                decorated().removeMapping(entry, index, previous);
                 return oldValue;
             }
             previous = entry;
@@ -679,15 +673,16 @@ public class MultiKeyMap
      * @param key5  the fifth key
      * @return true if the key matches
      */
-    protected boolean isEqualKey(AbstractHashedMap.HashEntry entry, Object key1, Object key2, Object key3, Object key4, Object key5) {
-        MultiKey multi = (MultiKey) entry.getKey();
+    protected boolean isEqualKey(AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry,
+            Object key1, Object key2, Object key3, Object key4, Object key5) {
+        MultiKey<? extends K> multi = entry.getKey();
         return
             multi.size() == 5 &&
-            (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) &&
-            (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1))) &&
-            (key3 == null ? multi.getKey(2) == null : key3.equals(multi.getKey(2))) &&
-            (key4 == null ? multi.getKey(3) == null : key4.equals(multi.getKey(3))) &&
-            (key5 == null ? multi.getKey(4) == null : key5.equals(multi.getKey(4)));
+            (key1 == multi.getKey(0) || key1 != null && key1.equals(multi.getKey(0))) &&
+            (key2 == multi.getKey(1) || key2 != null && key2.equals(multi.getKey(1))) &&
+            (key3 == multi.getKey(2) || key3 != null && key3.equals(multi.getKey(2))) &&
+            (key4 == multi.getKey(3) || key4 != null && key4.equals(multi.getKey(3))) &&
+            (key5 == multi.getKey(4) || key5 != null && key5.equals(multi.getKey(4)));
     }
 
     //-----------------------------------------------------------------------
@@ -702,9 +697,9 @@ public class MultiKeyMap
      */
     public boolean removeAll(Object key1) {
         boolean modified = false;
-        MapIterator it = mapIterator();
+        MapIterator<MultiKey<? extends K>, V> it = mapIterator();
         while (it.hasNext()) {
-            MultiKey multi = (MultiKey) it.next();
+            MultiKey<? extends K> multi = it.next();
             if (multi.size() >= 1 &&
                 (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0)))) {
                 it.remove();
@@ -726,9 +721,9 @@ public class MultiKeyMap
      */
     public boolean removeAll(Object key1, Object key2) {
         boolean modified = false;
-        MapIterator it = mapIterator();
+        MapIterator<MultiKey<? extends K>, V> it = mapIterator();
         while (it.hasNext()) {
-            MultiKey multi = (MultiKey) it.next();
+            MultiKey<? extends K> multi = it.next();
             if (multi.size() >= 2 &&
                 (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) &&
                 (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1)))) {
@@ -752,9 +747,9 @@ public class MultiKeyMap
      */
     public boolean removeAll(Object key1, Object key2, Object key3) {
         boolean modified = false;
-        MapIterator it = mapIterator();
+        MapIterator<MultiKey<? extends K>, V> it = mapIterator();
         while (it.hasNext()) {
-            MultiKey multi = (MultiKey) it.next();
+            MultiKey<? extends K> multi = it.next();
             if (multi.size() >= 3 &&
                 (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) &&
                 (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1))) &&
@@ -780,9 +775,9 @@ public class MultiKeyMap
      */
     public boolean removeAll(Object key1, Object key2, Object key3, Object key4) {
         boolean modified = false;
-        MapIterator it = mapIterator();
+        MapIterator<MultiKey<? extends K>, V> it = mapIterator();
         while (it.hasNext()) {
-            MultiKey multi = (MultiKey) it.next();
+            MultiKey<? extends K> multi = it.next();
             if (multi.size() >= 4 &&
                 (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) &&
                 (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1))) &&
@@ -801,13 +796,10 @@ public class MultiKeyMap
      * 
      * @param key  the key to check
      */
-    protected void checkKey(Object key) {
+    protected void checkKey(MultiKey<?> key) {
         if (key == null) {
             throw new NullPointerException("Key must not be null");
         }
-        if (key instanceof MultiKey == false) {
-            throw new ClassCastException("Key must be a MultiKey");
-        }
     }
 
     /**
@@ -815,8 +807,8 @@ public class MultiKeyMap
      *
      * @return a shallow clone
      */
-    public Object clone() {
-        return new MultiKeyMap((AbstractHashedMap) map.clone());
+    public MultiKeyMap<K, V> clone() {
+        return new MultiKeyMap<K, V>(decorated().clone());
     }
 
     /**
@@ -829,9 +821,9 @@ public class MultiKeyMap
      * @throws NullPointerException if the key is null
      * @throws ClassCastException if the key is not a MultiKey
      */
-    public Object put(Object key, Object value) {
+    public V put(MultiKey<? extends K> key, V value) {
         checkKey(key);
-        return map.put(key, value);
+        return super.put(key, value);
     }
 
     /**
@@ -842,72 +834,24 @@ public class MultiKeyMap
      * @throws NullPointerException if the mapToCopy or any key within is null
      * @throws ClassCastException if any key in mapToCopy is not a MultiKey
      */
-    public void putAll(Map mapToCopy) {
-        for (Iterator it = mapToCopy.keySet().iterator(); it.hasNext();) {
-            Object key = it.next();
+    @Override
+    public void putAll(Map<? extends MultiKey<? extends K>, ? extends V> mapToCopy) {
+        for (MultiKey<? extends K> key : mapToCopy.keySet()) {
             checkKey(key);
         }
-        map.putAll(mapToCopy);
+        super.putAll(mapToCopy);
     }
 
     //-----------------------------------------------------------------------
-    public MapIterator mapIterator() {
-        return map.mapIterator();
-    }
-
-    public int size() {
-        return map.size();
-    }
-
-    public boolean isEmpty() {
-        return map.isEmpty();
-    }
-
-    public boolean containsKey(Object key) {
-        return map.containsKey(key);
-    }
-
-    public boolean containsValue(Object value) {
-        return map.containsValue(value);
-    }
-
-    public Object get(Object key) {
-        return map.get(key);
-    }
-
-    public Object remove(Object key) {
-        return map.remove(key);
-    }
-
-    public void clear() {
-        map.clear();
+    public MapIterator<MultiKey<? extends K>, V> mapIterator() {
+        return decorated().mapIterator();
     }
 
-    public Set keySet() {
-        return map.keySet();
-    }
-
-    public Collection values() {
-        return map.values();
-    }
-
-    public Set entrySet() {
-        return map.entrySet();
-    }
-
-    public boolean equals(Object obj) {
-        if (obj == this) {
-            return true;
-        }
-        return map.equals(obj);
-    }
-
-    public int hashCode() {
-        return map.hashCode();
-    }
-
-    public String toString() {
-        return map.toString();
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected AbstractHashedMap<MultiKey<? extends K>, V> decorated() {
+        return map;
     }
-
 }

http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/MultiValueMap.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/commons/collections/map/MultiValueMap.java b/src/java/org/apache/commons/collections/map/MultiValueMap.java
index 04f6522..b7b7059 100644
--- a/src/java/org/apache/commons/collections/map/MultiValueMap.java
+++ b/src/java/org/apache/commons/collections/map/MultiValueMap.java
@@ -24,6 +24,7 @@ import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.Factory;
 import org.apache.commons.collections.FunctorException;
 import org.apache.commons.collections.MultiMap;
@@ -61,12 +62,12 @@ import org.apache.commons.collections.iterators.IteratorChain;
  * @version $Revision$ $Date$
  * @since Commons Collections 3.2
  */
-public class MultiValueMap extends AbstractMapDecorator implements MultiMap {
+public class MultiValueMap<K, V> extends AbstractMapDecorator<K, Object> implements MultiMap<K, V> {
 
     /** The factory for creating value collections. */
-    private final Factory collectionFactory;
+    private final Factory<? extends Collection<V>> collectionFactory;
     /** The cached values. */
-    private transient Collection values;
+    private transient Collection<V> values;
 
     /**
      * Creates a map which wraps the given map and
@@ -74,8 +75,9 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap {
      *
      * @param map  the map to wrap
      */
-    public static MultiValueMap decorate(Map map) {
-        return new MultiValueMap(map, new ReflectionFactory(ArrayList.class));
+    @SuppressWarnings("unchecked")
+    public static <K, V> MultiValueMap<K, V> decorate(Map<K, ? super Collection<V>> map) {
+        return MultiValueMap.<K, V, ArrayList>decorate((Map<K, ? super Collection>) map, ArrayList.class);
     }
 
     /**
@@ -85,8 +87,8 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap {
      * @param map  the map to wrap
      * @param collectionClass  the type of the collection class
      */
-    public static MultiValueMap decorate(Map map, Class collectionClass) {
-        return new MultiValueMap(map, new ReflectionFactory(collectionClass));
+    public static <K, V, C extends Collection<V>> MultiValueMap<K, V> decorate(Map<K, ? super C> map, Class<C> collectionClass) {
+        return new MultiValueMap<K, V>(map, new ReflectionFactory<C>(collectionClass));
     }
 
     /**
@@ -96,8 +98,8 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap {
      * @param map  the map to decorate
      * @param collectionFactory  the collection factory (must return a Collection object).
      */
-    public static MultiValueMap decorate(Map map, Factory collectionFactory) {
-        return new MultiValueMap(map, collectionFactory);
+    public static <K, V, C extends Collection<V>> MultiValueMap<K, V> decorate(Map<K, ? super C> map, Factory<C> collectionFactory) {
+        return new MultiValueMap<K, V>(map, collectionFactory);
     }
 
     //-----------------------------------------------------------------------
@@ -105,6 +107,7 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap {
      * Creates a MultiValueMap based on a <code>HashMap</code> and
      * storing the multiple values in an <code>ArrayList</code>.
      */
+    @SuppressWarnings("unchecked")
     public MultiValueMap() {
         this(new HashMap(), new ReflectionFactory(ArrayList.class));
     }
@@ -116,8 +119,9 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap {
      * @param map  the map to decorate
      * @param collectionFactory  the collection factory which must return a Collection instance
      */
-    protected MultiValueMap(Map map, Factory collectionFactory) {
-        super(map);
+    @SuppressWarnings("unchecked")
+    protected <C extends Collection<V>> MultiValueMap(Map<K, ? super C> map, Factory<C> collectionFactory) {
+        super((Map<K, Object>) map);
         if (collectionFactory == null) {
             throw new IllegalArgumentException("The factory must not be null");
         }
@@ -153,8 +157,9 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap {
      * @param value the value to remove
      * @return the value removed (which was passed in), null if nothing removed
      */
-    public Object remove(Object key, Object value) {
-        Collection valuesForKey = getCollection(key);
+    @SuppressWarnings("unchecked")
+    public V remove(Object key, Object value) {
+        Collection<V> valuesForKey = getCollection(key);
         if (valuesForKey == null) {
             return null;
         }
@@ -165,7 +170,7 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap {
         if (valuesForKey.isEmpty()) {
             remove(key);
         }
-        return value;
+        return (V) value;
     }
 
     /**
@@ -176,17 +181,14 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap {
      * @param value  the value to search for
      * @return true if the map contains the value
      */
+    @SuppressWarnings("unchecked")
     public boolean containsValue(Object value) {
-        Set pairs = decorated().entrySet();
-        if (pairs == null) {
-            return false;
-        }
-        Iterator pairsIterator = pairs.iterator();
-        while (pairsIterator.hasNext()) {
-            Map.Entry keyValuePair = (Map.Entry) pairsIterator.next();
-            Collection coll = (Collection) keyValuePair.getValue();
-            if (coll.contains(value)) {
-                return true;
+        Set<Map.Entry<K, Object>> pairs = decorated().entrySet();
+        if (pairs != null) {
+            for (Map.Entry<K, Object> entry : pairs) {
+                if (((Collection<V>) entry.getValue()).contains(value)) {
+                    return true;
+                }
             }
         }
         return false;
@@ -202,19 +204,20 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap {
      * @param value  the value to add to the collection at the key
      * @return the value added if the map changed and null if the map did not change
      */
-    public Object put(Object key, Object value) {
+    @SuppressWarnings("unchecked")
+    public Object put(K key, Object value) {
         boolean result = false;
-        Collection coll = getCollection(key);
+        Collection<V> coll = getCollection(key);
         if (coll == null) {
             coll = createCollection(1);  // might produce a non-empty collection
-            coll.add(value);
+            coll.add((V) value);
             if (coll.size() > 0) {
                 // only add if non-zero size to maintain class state
                 decorated().put(key, coll);
                 result = true;  // map definitely changed
             }
         } else {
-            result = coll.add(value);
+            result = coll.add((V) value);
         }
         return (result ? value : null);
     }
@@ -230,17 +233,15 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap {
      *
      * @param map  the map to copy (either a normal or multi map)
      */
-    public void putAll(Map map) {
+    @SuppressWarnings("unchecked")
+    public void putAll(Map<? extends K, ?> map) {
         if (map instanceof MultiMap) {
-            for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
-                Map.Entry entry = (Map.Entry) it.next();
-                Collection coll = (Collection) entry.getValue();
-                putAll(entry.getKey(), coll);
+            for (Map.Entry<? extends K, Object> entry : ((MultiMap<? extends K, V>) map).entrySet()) {
+                putAll(entry.getKey(), (Collection<V>) entry.getValue());
             }
         } else {
-            for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
-                Map.Entry entry = (Map.Entry) it.next();
-                put(entry.getKey(), entry.getValue());
+            for (Map.Entry<? extends K, ?> entry : map.entrySet()) {
+                put(entry.getKey(), (V) entry.getValue());
             }
         }
     }
@@ -252,9 +253,10 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap {
      *
      * @return a collection view of the values contained in this map
      */
-    public Collection values() {
-        Collection vs = values;
-        return (vs != null ? vs : (values = new Values()));
+    @SuppressWarnings("unchecked")
+    public Collection<Object> values() {
+        Collection<V> vs = values;
+        return (Collection<Object>) (vs != null ? vs : (values = new Values()));
     }
 
     /**
@@ -264,7 +266,7 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap {
      * @return true if the map contains the value
      */
     public boolean containsValue(Object key, Object value) {
-        Collection coll = getCollection(key);
+        Collection<V> coll = getCollection(key);
         if (coll == null) {
             return false;
         }
@@ -278,8 +280,9 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap {
      * @param key  the key to retrieve
      * @return the collection mapped to the key, null if no mapping
      */
-    public Collection getCollection(Object key) {
-        return (Collection) decorated().get(key);
+    @SuppressWarnings("unchecked")
+    public Collection<V> getCollection(Object key) {
+        return (Collection<V>) decorated().get(key);
     }
 
     /**
@@ -289,7 +292,7 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap {
      * @return the size of the collection at the key, zero if key not in map
      */
     public int size(Object key) {
-        Collection coll = getCollection(key);
+        Collection<V> coll = getCollection(key);
         if (coll == null) {
             return 0;
         }
@@ -304,12 +307,12 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap {
      * @param values  the values to add to the collection at the key, null ignored
      * @return true if this map changed
      */
-    public boolean putAll(Object key, Collection values) {
+    public boolean putAll(K key, Collection<V> values) {
         if (values == null || values.size() == 0) {
             return false;
         }
         boolean result = false;
-        Collection coll = getCollection(key);
+        Collection<V> coll = getCollection(key);
         if (coll == null) {
             coll = createCollection(values.size());  // might produce a non-empty collection
             coll.addAll(values);
@@ -330,12 +333,11 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap {
      * @param key  the key to get an iterator for
      * @return the iterator of the collection at the key, empty iterator if key not in map
      */
-    public Iterator iterator(Object key) {
+    public Iterator<V> iterator(Object key) {
         if (!containsKey(key)) {
-            return EmptyIterator.INSTANCE;
-        } else {
-            return new ValuesIterator(key);
+            return EmptyIterator.<V>getInstance();
         }
+        return new ValuesIterator(key);
     }
 
     /**
@@ -345,10 +347,8 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap {
      */
     public int totalSize() {
         int total = 0;
-        Collection values = decorated().values();
-        for (Iterator it = values.iterator(); it.hasNext();) {
-            Collection coll = (Collection) it.next();
-            total += coll.size();
+        for (Object v : decorated().values()) {
+            total += CollectionUtils.size(v);
         }
         return total;
     }
@@ -363,18 +363,18 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap {
      * @param size  the collection size that is about to be added
      * @return the new collection
      */
-    protected Collection createCollection(int size) {
-        return (Collection) collectionFactory.create();
+    protected Collection<V> createCollection(int size) {
+        return collectionFactory.create();
     }
 
     //-----------------------------------------------------------------------
     /**
      * Inner class that provides the values view.
      */
-    private class Values extends AbstractCollection {
-        public Iterator iterator() {
-            final IteratorChain chain = new IteratorChain();
-            for (Iterator it = keySet().iterator(); it.hasNext();) {
+    private class Values extends AbstractCollection<V> {
+        public Iterator<V> iterator() {
+            final IteratorChain<V> chain = new IteratorChain<V>();
+            for (Iterator<K> it = keySet().iterator(); it.hasNext();) {
                 chain.addIterator(new ValuesIterator(it.next()));
             }
             return chain;
@@ -392,10 +392,10 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap {
     /**
      * Inner class that provides the values iterator.
      */
-    private class ValuesIterator implements Iterator {
+    private class ValuesIterator implements Iterator<V> {
         private final Object key;
-        private final Collection values;
-        private final Iterator iterator;
+        private final Collection<V> values;
+        private final Iterator<V> iterator;
 
         public ValuesIterator(Object key) {
             this.key = key;
@@ -414,7 +414,7 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap {
             return iterator.hasNext();
         }
 
-        public Object next() {
+        public V next() {
             return iterator.next();
         }
     }
@@ -422,14 +422,14 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap {
     /**
      * Inner class that provides a simple reflection factory.
      */
-    private static class ReflectionFactory implements Factory {
-        private final Class clazz;
+    private static class ReflectionFactory<T extends Collection<?>> implements Factory<T> {
+        private final Class<T> clazz;
 
-        public ReflectionFactory(Class clazz) {
+        public ReflectionFactory(Class<T> clazz) {
             this.clazz = clazz;
         }
 
-        public Object create() {
+        public T create() {
             try {
                 return clazz.newInstance();
             } catch (Exception ex) {

http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/PredicatedMap.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/commons/collections/map/PredicatedMap.java b/src/java/org/apache/commons/collections/map/PredicatedMap.java
index b334157..537fe35 100644
--- a/src/java/org/apache/commons/collections/map/PredicatedMap.java
+++ b/src/java/org/apache/commons/collections/map/PredicatedMap.java
@@ -50,17 +50,18 @@ import org.apache.commons.collections.Predicate;
  * @author Stephen Colebourne
  * @author Paul Jack
  */
-public class PredicatedMap
-        extends AbstractInputCheckedMapDecorator
+public class PredicatedMap<K, V>
+        extends AbstractInputCheckedMapDecorator<K, V>
         implements Serializable {
 
     /** Serialization version */
     private static final long serialVersionUID = 7412622456128415156L;
 
     /** The key predicate to use */
-    protected final Predicate keyPredicate;
+    protected final Predicate<? super K> keyPredicate;
+
     /** The value predicate to use */
-    protected final Predicate valuePredicate;
+    protected final Predicate<? super V> valuePredicate;
 
     /**
      * Factory method to create a predicated (validating) map.
@@ -73,8 +74,8 @@ public class PredicatedMap
      * @param valuePredicate  the predicate to validate to values, null means no check
      * @throws IllegalArgumentException if the map is null
      */
-    public static Map decorate(Map map, Predicate keyPredicate, Predicate valuePredicate) {
-        return new PredicatedMap(map, keyPredicate, valuePredicate);
+    public static <K, V> Map<K, V> decorate(Map<K, V> map, Predicate<? super K> keyPredicate, Predicate<? super V> valuePredicate) {
+        return new PredicatedMap<K, V>(map, keyPredicate, valuePredicate);
     }
 
     //-----------------------------------------------------------------------
@@ -86,17 +87,15 @@ public class PredicatedMap
      * @param valuePredicate  the predicate to validate to values, null means no check
      * @throws IllegalArgumentException if the map is null
      */
-    protected PredicatedMap(Map map, Predicate keyPredicate, Predicate valuePredicate) {
+    protected PredicatedMap(Map<K, V> map, Predicate<? super K> keyPredicate, Predicate<? super V> valuePredicate) {
         super(map);
         this.keyPredicate = keyPredicate;
         this.valuePredicate = valuePredicate;
         
-        Iterator it = map.entrySet().iterator();
+        Iterator<Map.Entry<K, V>> it = map.entrySet().iterator();
         while (it.hasNext()) {
-            Map.Entry entry = (Map.Entry) it.next();
-            Object key = entry.getKey();
-            Object value = entry.getValue();
-            validate(key, value);
+            Map.Entry<K, V> entry = it.next();
+            validate(entry.getKey(), entry.getValue());
         }
     }
 
@@ -121,6 +120,7 @@ public class PredicatedMap
      * @throws ClassNotFoundException
      * @since Commons Collections 3.1
      */
+    @SuppressWarnings("unchecked")
     private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
         in.defaultReadObject();
         map = (Map) in.readObject();
@@ -134,7 +134,7 @@ public class PredicatedMap
      * @param value  the value to validate
      * @throws IllegalArgumentException if invalid
      */
-    protected void validate(Object key, Object value) {
+    protected void validate(K key, V value) {
         if (keyPredicate != null && keyPredicate.evaluate(key) == false) {
             throw new IllegalArgumentException("Cannot add key - Predicate rejected it");
         }
@@ -150,7 +150,7 @@ public class PredicatedMap
      * @throws IllegalArgumentException if invalid
      * @since Commons Collections 3.1
      */
-    protected Object checkSetValue(Object value) {
+    protected V checkSetValue(V value) {
         if (valuePredicate.evaluate(value) == false) {
             throw new IllegalArgumentException("Cannot set value - Predicate rejected it");
         }
@@ -168,20 +168,16 @@ public class PredicatedMap
     }
 
     //-----------------------------------------------------------------------
-    public Object put(Object key, Object value) {
+    public V put(K key, V value) {
         validate(key, value);
         return map.put(key, value);
     }
 
-    public void putAll(Map mapToCopy) {
-        Iterator it = mapToCopy.entrySet().iterator();
-        while (it.hasNext()) {
-            Map.Entry entry = (Map.Entry) it.next();
-            Object key = entry.getKey();
-            Object value = entry.getValue();
-            validate(key, value);
+    public void putAll(Map<? extends K, ? extends V> mapToCopy) {
+        for (Map.Entry<? extends K, ? extends V> entry : mapToCopy.entrySet()) {
+            validate(entry.getKey(), entry.getValue());
         }
-        map.putAll(mapToCopy);
+        super.putAll(mapToCopy);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/PredicatedSortedMap.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/commons/collections/map/PredicatedSortedMap.java b/src/java/org/apache/commons/collections/map/PredicatedSortedMap.java
index d1b39e3..63f75a3 100644
--- a/src/java/org/apache/commons/collections/map/PredicatedSortedMap.java
+++ b/src/java/org/apache/commons/collections/map/PredicatedSortedMap.java
@@ -46,9 +46,7 @@ import org.apache.commons.collections.Predicate;
  * @author Stephen Colebourne
  * @author Paul Jack
  */
-public class PredicatedSortedMap
-        extends PredicatedMap
-        implements SortedMap {
+public class PredicatedSortedMap<K, V> extends PredicatedMap<K, V> implements SortedMap<K, V> {
 
     /** Serialization version */
     private static final long serialVersionUID = 3359846175935304332L;
@@ -64,8 +62,9 @@ public class PredicatedSortedMap
      * @param valuePredicate  the predicate to validate to values, null means no check
      * @throws IllegalArgumentException if the map is null
      */
-    public static SortedMap decorate(SortedMap map, Predicate keyPredicate, Predicate valuePredicate) {
-        return new PredicatedSortedMap(map, keyPredicate, valuePredicate);
+    public static <K, V> SortedMap<K, V> decorate(SortedMap<K, V> map,
+            Predicate<? super K> keyPredicate, Predicate<? super V> valuePredicate) {
+        return new PredicatedSortedMap<K, V>(map, keyPredicate, valuePredicate);
     }
 
     //-----------------------------------------------------------------------
@@ -77,7 +76,8 @@ public class PredicatedSortedMap
      * @param valuePredicate  the predicate to validate to values, null means no check
      * @throws IllegalArgumentException if the map is null
      */
-    protected PredicatedSortedMap(SortedMap map, Predicate keyPredicate, Predicate valuePredicate) {
+    protected PredicatedSortedMap(SortedMap<K, V> map, Predicate<? super K> keyPredicate,
+            Predicate<? super V> valuePredicate) {
         super(map, keyPredicate, valuePredicate);
     }
 
@@ -87,36 +87,36 @@ public class PredicatedSortedMap
      * 
      * @return the decorated map
      */
-    protected SortedMap getSortedMap() {
-        return (SortedMap) map;
+    protected SortedMap<K, V> getSortedMap() {
+        return (SortedMap<K, V>) map;
     }
 
     //-----------------------------------------------------------------------
-    public Object firstKey() {
+    public K firstKey() {
         return getSortedMap().firstKey();
     }
 
-    public Object lastKey() {
+    public K lastKey() {
         return getSortedMap().lastKey();
     }
 
-    public Comparator comparator() {
+    public Comparator<? super K> comparator() {
         return getSortedMap().comparator();
     }
 
-    public SortedMap subMap(Object fromKey, Object toKey) {
-        SortedMap map = getSortedMap().subMap(fromKey, toKey);
-        return new PredicatedSortedMap(map, keyPredicate, valuePredicate);
+    public SortedMap<K, V> subMap(K fromKey, K toKey) {
+        SortedMap<K, V> map = getSortedMap().subMap(fromKey, toKey);
+        return new PredicatedSortedMap<K, V>(map, keyPredicate, valuePredicate);
     }
 
-    public SortedMap headMap(Object toKey) {
-        SortedMap map = getSortedMap().headMap(toKey);
-        return new PredicatedSortedMap(map, keyPredicate, valuePredicate);
+    public SortedMap<K, V> headMap(K toKey) {
+        SortedMap<K, V> map = getSortedMap().headMap(toKey);
+        return new PredicatedSortedMap<K, V>(map, keyPredicate, valuePredicate);
     }
 
-    public SortedMap tailMap(Object fromKey) {
-        SortedMap map = getSortedMap().tailMap(fromKey);
-        return new PredicatedSortedMap(map, keyPredicate, valuePredicate);
+    public SortedMap<K, V> tailMap(K fromKey) {
+        SortedMap<K, V> map = getSortedMap().tailMap(fromKey);
+        return new PredicatedSortedMap<K, V>(map, keyPredicate, valuePredicate);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/ReferenceIdentityMap.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/commons/collections/map/ReferenceIdentityMap.java b/src/java/org/apache/commons/collections/map/ReferenceIdentityMap.java
index 39fba2b..7a6ac47 100644
--- a/src/java/org/apache/commons/collections/map/ReferenceIdentityMap.java
+++ b/src/java/org/apache/commons/collections/map/ReferenceIdentityMap.java
@@ -70,7 +70,7 @@ import java.lang.ref.Reference;
  * 
  * @author Stephen Colebourne
  */
-public class ReferenceIdentityMap extends AbstractReferenceMap implements Serializable {
+public class ReferenceIdentityMap<K, V> extends AbstractReferenceMap<K, V> implements Serializable {
 
     /** Serialization version */
     private static final long serialVersionUID = -1266190134568365852L;
@@ -80,7 +80,8 @@ public class ReferenceIdentityMap extends AbstractReferenceMap implements Serial
      * use hard references to keys and soft references to values.
      */
     public ReferenceIdentityMap() {
-        super(HARD, SOFT, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, false);
+        super(ReferenceStrength.HARD, ReferenceStrength.SOFT, DEFAULT_CAPACITY,
+                DEFAULT_LOAD_FACTOR, false);
     }
 
     /**
@@ -92,7 +93,7 @@ public class ReferenceIdentityMap extends AbstractReferenceMap implements Serial
      * @param valueType  the type of reference to use for values;
      *   must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
      */
-    public ReferenceIdentityMap(int keyType, int valueType) {
+    public ReferenceIdentityMap(ReferenceStrength keyType, ReferenceStrength valueType) {
         super(keyType, valueType, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, false);
     }
 
@@ -107,7 +108,8 @@ public class ReferenceIdentityMap extends AbstractReferenceMap implements Serial
      * @param purgeValues should the value be automatically purged when the 
      *   key is garbage collected 
      */
-    public ReferenceIdentityMap(int keyType, int valueType, boolean purgeValues) {
+    public ReferenceIdentityMap(ReferenceStrength keyType, ReferenceStrength valueType,
+            boolean purgeValues) {
         super(keyType, valueType, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, purgeValues);
     }
 
@@ -122,7 +124,8 @@ public class ReferenceIdentityMap extends AbstractReferenceMap implements Serial
      * @param capacity  the initial capacity for the map
      * @param loadFactor  the load factor for the map
      */
-    public ReferenceIdentityMap(int keyType, int valueType, int capacity, float loadFactor) {
+    public ReferenceIdentityMap(ReferenceStrength keyType, ReferenceStrength valueType,
+            int capacity, float loadFactor) {
         super(keyType, valueType, capacity, loadFactor, false);
     }
 
@@ -139,8 +142,8 @@ public class ReferenceIdentityMap extends AbstractReferenceMap implements Serial
      * @param purgeValues  should the value be automatically purged when the 
      *   key is garbage collected 
      */
-    public ReferenceIdentityMap(int keyType, int valueType, int capacity,
-                        float loadFactor, boolean purgeValues) {
+    public ReferenceIdentityMap(ReferenceStrength keyType, ReferenceStrength valueType,
+            int capacity, float loadFactor, boolean purgeValues) {
         super(keyType, valueType, capacity, loadFactor, purgeValues);
     }
 
@@ -182,8 +185,8 @@ public class ReferenceIdentityMap extends AbstractReferenceMap implements Serial
      * @return true if equal by identity
      */
     protected boolean isEqualKey(Object key1, Object key2) {
-        key2 = (keyType > HARD ? ((Reference) key2).get() : key2);
-        return (key1 == key2);
+        key2 = keyType == ReferenceStrength.HARD ? key2 : ((Reference<?>) key2).get();
+        return key1 == key2;
     }
 
     /**
@@ -196,7 +199,7 @@ public class ReferenceIdentityMap extends AbstractReferenceMap implements Serial
      * @return true if equal by identity
      */
     protected boolean isEqualValue(Object value1, Object value2) {
-        return (value1 == value2);
+        return value1 == value2;
     }
 
     //-----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/ReferenceMap.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/commons/collections/map/ReferenceMap.java b/src/java/org/apache/commons/collections/map/ReferenceMap.java
index 5685711..861db7f 100644
--- a/src/java/org/apache/commons/collections/map/ReferenceMap.java
+++ b/src/java/org/apache/commons/collections/map/ReferenceMap.java
@@ -73,7 +73,7 @@ import java.io.Serializable;
  * @author Paul Jack
  * @author Stephen Colebourne
  */
-public class ReferenceMap extends AbstractReferenceMap implements Serializable {
+public class ReferenceMap<K, V> extends AbstractReferenceMap<K, V> implements Serializable {
 
     /** Serialization version */
     private static final long serialVersionUID = 1555089888138299607L;
@@ -83,7 +83,8 @@ public class ReferenceMap extends AbstractReferenceMap implements Serializable {
      * use hard references to keys and soft references to values.
      */
     public ReferenceMap() {
-        super(HARD, SOFT, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, false);
+        super(ReferenceStrength.HARD, ReferenceStrength.SOFT, DEFAULT_CAPACITY,
+                DEFAULT_LOAD_FACTOR, false);
     }
 
     /**
@@ -95,7 +96,7 @@ public class ReferenceMap extends AbstractReferenceMap implements Serializable {
      * @param valueType  the type of reference to use for values;
      *   must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
      */
-    public ReferenceMap(int keyType, int valueType) {
+    public ReferenceMap(ReferenceStrength keyType, ReferenceStrength valueType) {
         super(keyType, valueType, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, false);
     }
 
@@ -110,7 +111,7 @@ public class ReferenceMap extends AbstractReferenceMap implements Serializable {
      * @param purgeValues should the value be automatically purged when the 
      *   key is garbage collected 
      */
-    public ReferenceMap(int keyType, int valueType, boolean purgeValues) {
+    public ReferenceMap(ReferenceStrength keyType, ReferenceStrength valueType, boolean purgeValues) {
         super(keyType, valueType, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, purgeValues);
     }
 
@@ -126,7 +127,8 @@ public class ReferenceMap extends AbstractReferenceMap implements Serializable {
      * @param capacity  the initial capacity for the map
      * @param loadFactor  the load factor for the map
      */
-    public ReferenceMap(int keyType, int valueType, int capacity, float loadFactor) {
+    public ReferenceMap(ReferenceStrength keyType, ReferenceStrength valueType, int capacity,
+            float loadFactor) {
         super(keyType, valueType, capacity, loadFactor, false);
     }
 
@@ -144,8 +146,8 @@ public class ReferenceMap extends AbstractReferenceMap implements Serializable {
      * @param purgeValues  should the value be automatically purged when the 
      *   key is garbage collected 
      */
-    public ReferenceMap(int keyType, int valueType, int capacity,
-                        float loadFactor, boolean purgeValues) {
+    public ReferenceMap(ReferenceStrength keyType, ReferenceStrength valueType, int capacity,
+            float loadFactor, boolean purgeValues) {
         super(keyType, valueType, capacity, loadFactor, purgeValues);
     }