http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/AbstractInputCheckedMapDecorator.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/commons/collections/map/AbstractInputCheckedMapDecorator.java
 
b/src/java/org/apache/commons/collections/map/AbstractInputCheckedMapDecorator.java
index 0add873..e8be0cd 100644
--- 
a/src/java/org/apache/commons/collections/map/AbstractInputCheckedMapDecorator.java
+++ 
b/src/java/org/apache/commons/collections/map/AbstractInputCheckedMapDecorator.java
@@ -44,8 +44,8 @@ import 
org.apache.commons.collections.set.AbstractSetDecorator;
  * 
  * @author Stephen Colebourne
  */
-abstract class AbstractInputCheckedMapDecorator
-        extends AbstractMapDecorator {
+abstract class AbstractInputCheckedMapDecorator<K, V>
+        extends AbstractMapDecorator<K, V> {
 
     /**
      * Constructor only used in deserialization, do not use otherwise.
@@ -60,7 +60,7 @@ abstract class AbstractInputCheckedMapDecorator
      * @param map  the map to decorate, must not be null
      * @throws IllegalArgumentException if map is null
      */
-    protected AbstractInputCheckedMapDecorator(Map map) {
+    protected AbstractInputCheckedMapDecorator(Map<K, V> map) {
         super(map);
     }
 
@@ -79,7 +79,7 @@ abstract class AbstractInputCheckedMapDecorator
      * @throws ClassCastException if the class of the specified value is 
invalid
      * @throws NullPointerException if the specified value is null and nulls 
are invalid
      */
-    protected abstract Object checkSetValue(Object value);
+    protected abstract V checkSetValue(V value);
 
     /**
      * Hook method called to determine if <code>checkSetValue</code> has any 
effect.
@@ -96,41 +96,43 @@ abstract class AbstractInputCheckedMapDecorator
     }
 
     //-----------------------------------------------------------------------
-    public Set entrySet() {
+    public Set<Map.Entry<K, V>> entrySet() {
         if (isSetValueChecking()) {
             return new EntrySet(map.entrySet(), this);
-        } else {
-            return map.entrySet();
         }
+        return map.entrySet();
     }
 
     //-----------------------------------------------------------------------
     /**
      * Implementation of an entry set that checks additions via setValue.
      */
-    static class EntrySet extends AbstractSetDecorator {
+    @SuppressWarnings("serial")
+    private class EntrySet extends AbstractSetDecorator<Map.Entry<K, V>> {
         
         /** The parent map */
-        private final AbstractInputCheckedMapDecorator parent;
+        private final AbstractInputCheckedMapDecorator<K, V> parent;
 
-        protected EntrySet(Set set, AbstractInputCheckedMapDecorator parent) {
+        protected EntrySet(Set<Map.Entry<K, V>> set, 
AbstractInputCheckedMapDecorator<K, V> parent) {
             super(set);
             this.parent = parent;
         }
 
-        public Iterator iterator() {
+        public Iterator<Map.Entry<K, V>> iterator() {
             return new EntrySetIterator(collection.iterator(), parent);
         }
         
+        @SuppressWarnings("unchecked")
         public Object[] toArray() {
             Object[] array = collection.toArray();
             for (int i = 0; i < array.length; i++) {
-                array[i] = new MapEntry((Map.Entry) array[i], parent);
+                array[i] = new MapEntry((Map.Entry<K, V>) array[i], parent);
             }
             return array;
         }
         
-        public Object[] toArray(Object array[]) {
+        @SuppressWarnings("unchecked")
+        public <T> T[] toArray(T[] array) {
             Object[] result = array;
             if (array.length > 0) {
                 // we must create a new array to handle multi-threaded 
situations
@@ -139,12 +141,12 @@ abstract class AbstractInputCheckedMapDecorator
             }
             result = collection.toArray(result);
             for (int i = 0; i < result.length; i++) {
-                result[i] = new MapEntry((Map.Entry) result[i], parent);
+                result[i] = new MapEntry((Map.Entry<K, V>) result[i], parent);
             }
 
             // check to see if result should be returned straight
             if (result.length > array.length) {
-                return result;
+                return (T[]) result;
             }
 
             // copy back into input array to fulfil the method contract
@@ -159,18 +161,18 @@ abstract class AbstractInputCheckedMapDecorator
     /**
      * Implementation of an entry set iterator that checks additions via 
setValue.
      */
-    static class EntrySetIterator extends AbstractIteratorDecorator {
-        
+    private class EntrySetIterator extends 
AbstractIteratorDecorator<Map.Entry<K, V>> {
+
         /** The parent map */
-        private final AbstractInputCheckedMapDecorator parent;
-        
-        protected EntrySetIterator(Iterator iterator, 
AbstractInputCheckedMapDecorator parent) {
+        private final AbstractInputCheckedMapDecorator<K, V> parent;
+
+        protected EntrySetIterator(Iterator<Map.Entry<K, V>> iterator, 
AbstractInputCheckedMapDecorator<K, V> parent) {
             super(iterator);
             this.parent = parent;
         }
-        
-        public Object next() {
-            Map.Entry entry = (Map.Entry) iterator.next();
+
+        public Map.Entry<K, V> next() {
+            Map.Entry<K, V> entry = iterator.next();
             return new MapEntry(entry, parent);
         }
     }
@@ -178,17 +180,17 @@ abstract class AbstractInputCheckedMapDecorator
     /**
      * Implementation of a map entry that checks additions via setValue.
      */
-    static class MapEntry extends AbstractMapEntryDecorator {
+    private class MapEntry extends AbstractMapEntryDecorator<K, V> {
 
         /** The parent map */
-        private final AbstractInputCheckedMapDecorator parent;
+        private final AbstractInputCheckedMapDecorator<K, V> parent;
 
-        protected MapEntry(Map.Entry entry, AbstractInputCheckedMapDecorator 
parent) {
+        protected MapEntry(Map.Entry<K, V> entry, 
AbstractInputCheckedMapDecorator<K, V> parent) {
             super(entry);
             this.parent = parent;
         }
 
-        public Object setValue(Object value) {
+        public V setValue(V value) {
             value = parent.checkSetValue(value);
             return entry.setValue(value);
         }

http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/AbstractLinkedMap.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/commons/collections/map/AbstractLinkedMap.java 
b/src/java/org/apache/commons/collections/map/AbstractLinkedMap.java
index 4a735a5..9086918 100644
--- a/src/java/org/apache/commons/collections/map/AbstractLinkedMap.java
+++ b/src/java/org/apache/commons/collections/map/AbstractLinkedMap.java
@@ -21,7 +21,6 @@ import java.util.Iterator;
 import java.util.Map;
 import java.util.NoSuchElementException;
 
-import org.apache.commons.collections.MapIterator;
 import org.apache.commons.collections.OrderedIterator;
 import org.apache.commons.collections.OrderedMap;
 import org.apache.commons.collections.OrderedMapIterator;
@@ -63,10 +62,10 @@ import 
org.apache.commons.collections.iterators.EmptyOrderedMapIterator;
  * @author java util LinkedHashMap
  * @author Stephen Colebourne
  */
-public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap 
{
+public abstract class AbstractLinkedMap<K, V> extends AbstractHashedMap<K, V> 
implements OrderedMap<K, V> {
     
     /** Header in the linked list */
-    protected transient LinkEntry header;
+    protected transient LinkEntry<K, V> header;
 
     /**
      * Constructor only used in deserialization, do not use otherwise.
@@ -115,7 +114,7 @@ public class AbstractLinkedMap extends AbstractHashedMap 
implements OrderedMap {
      * @param map  the map to copy
      * @throws NullPointerException if the map is null
      */
-    protected AbstractLinkedMap(Map map) {
+    protected AbstractLinkedMap(Map<K, V> map) {
         super(map);
     }
 
@@ -127,7 +126,7 @@ public class AbstractLinkedMap extends AbstractHashedMap 
implements OrderedMap {
      * the map entry object.
      */
     protected void init() {
-        header = (LinkEntry) createEntry(null, -1, null, null);
+        header = createEntry(null, -1, null, null);
         header.before = header.after = header;
     }
 
@@ -141,13 +140,13 @@ public class AbstractLinkedMap extends AbstractHashedMap 
implements OrderedMap {
     public boolean containsValue(Object value) {
         // override uses faster iterator
         if (value == null) {
-            for (LinkEntry entry = header.after; entry != header; entry = 
entry.after) {
+            for (LinkEntry<K, V> entry = header.after; entry != header; entry 
= entry.after) {
                 if (entry.getValue() == null) {
                     return true;
                 }
             }
         } else {
-            for (LinkEntry entry = header.after; entry != header; entry = 
entry.after) {
+            for (LinkEntry<K, V> entry = header.after; entry != header; entry 
= entry.after) {
                 if (isEqualValue(value, entry.getValue())) {
                     return true;
                 }
@@ -172,7 +171,7 @@ public class AbstractLinkedMap extends AbstractHashedMap 
implements OrderedMap {
      * 
      * @return the most recently inserted key
      */
-    public Object firstKey() {
+    public K firstKey() {
         if (size == 0) {
             throw new NoSuchElementException("Map is empty");
         }
@@ -184,7 +183,7 @@ public class AbstractLinkedMap extends AbstractHashedMap 
implements OrderedMap {
      * 
      * @return the eldest key
      */
-    public Object lastKey() {
+    public K lastKey() {
         if (size == 0) {
             throw new NoSuchElementException("Map is empty");
         }
@@ -197,19 +196,23 @@ public class AbstractLinkedMap extends AbstractHashedMap 
implements OrderedMap {
      * @param key  the key to get after
      * @return the next key
      */
-    public Object nextKey(Object key) {
-        LinkEntry entry = (LinkEntry) getEntry(key);
+    public K nextKey(Object key) {
+        LinkEntry<K, V> entry = getEntry(key);
         return (entry == null || entry.after == header ? null : 
entry.after.getKey());
     }
 
+    protected LinkEntry<K, V> getEntry(Object key) {
+        return (LinkEntry<K, V>) super.getEntry(key);
+    }
+
     /**
      * Gets the previous key in sequence.
      * 
      * @param key  the key to get before
      * @return the previous key
      */
-    public Object previousKey(Object key) {
-        LinkEntry entry = (LinkEntry) getEntry(key);
+    public K previousKey(Object key) {
+        LinkEntry<K, V> entry = getEntry(key);
         return (entry == null || entry.before == header ? null : 
entry.before.getKey());
     }
 
@@ -221,14 +224,14 @@ public class AbstractLinkedMap extends AbstractHashedMap 
implements OrderedMap {
      * @return the key at the specified index
      * @throws IndexOutOfBoundsException if the index is invalid
      */
-    protected LinkEntry getEntry(int index) {
+    protected LinkEntry<K, V> getEntry(int index) {
         if (index < 0) {
             throw new IndexOutOfBoundsException("Index " + index + " is less 
than zero");
         }
         if (index >= size) {
             throw new IndexOutOfBoundsException("Index " + index + " is 
invalid for size " + size);
         }
-        LinkEntry entry;
+        LinkEntry<K, V> entry;
         if (index < (size / 2)) {
             // Search forwards
             entry = header.after;
@@ -251,18 +254,18 @@ public class AbstractLinkedMap extends AbstractHashedMap 
implements OrderedMap {
      * This implementation adds the entry to the data storage table and
      * to the end of the linked list.
      * 
-     * @param entry  the entry to add
+     * @param link  the entry to add
      * @param hashIndex  the index into the data array to store at
      */
-    protected void addEntry(HashEntry entry, int hashIndex) {
-        LinkEntry link = (LinkEntry) entry;
+    protected void addEntry(HashEntry<K, V> entry, int hashIndex) {
+        LinkEntry<K, V> link = (LinkEntry<K, V>) entry;
         link.after  = header;
         link.before = header.before;
         header.before.after = link;
         header.before = link;
-        data[hashIndex] = entry;
+        data[hashIndex] = link;
     }
-    
+
     /**
      * Creates an entry to store the data.
      * <p>
@@ -274,10 +277,10 @@ public class AbstractLinkedMap extends AbstractHashedMap 
implements OrderedMap {
      * @param value  the value to store
      * @return the newly created entry
      */
-    protected HashEntry createEntry(HashEntry next, int hashCode, Object key, 
Object value) {
-        return new LinkEntry(next, hashCode, key, value);
+    protected LinkEntry<K, V> createEntry(HashEntry<K, V> next, int hashCode, 
K key, V value) {
+        return new LinkEntry<K, V>(next, hashCode, convertKey(key), value);
     }
-    
+
     /**
      * Removes an entry from the map and the linked list.
      * <p>
@@ -288,15 +291,15 @@ public class AbstractLinkedMap extends AbstractHashedMap 
implements OrderedMap {
      * @param hashIndex  the index into the data structure
      * @param previous  the previous entry in the chain
      */
-    protected void removeEntry(HashEntry entry, int hashIndex, HashEntry 
previous) {
-        LinkEntry link = (LinkEntry) entry;
+    protected void removeEntry(HashEntry<K, V> entry, int hashIndex, 
HashEntry<K, V> previous) {
+        LinkEntry<K, V> link = (LinkEntry<K, V>) entry;
         link.before.after = link.after;
         link.after.before = link.before;
         link.after = null;
         link.before = null;
         super.removeEntry(entry, hashIndex, previous);
     }
-    
+
     //-----------------------------------------------------------------------
     /**
      * Gets the <code>before</code> field from a <code>LinkEntry</code>.
@@ -307,10 +310,10 @@ public class AbstractLinkedMap extends AbstractHashedMap 
implements OrderedMap {
      * @throws NullPointerException if the entry is null
      * @since Commons Collections 3.1
      */
-    protected LinkEntry entryBefore(LinkEntry entry) {
+    protected LinkEntry<K, V> entryBefore(LinkEntry<K, V> entry) {
         return entry.before;
     }
-    
+
     /**
      * Gets the <code>after</code> field from a <code>LinkEntry</code>.
      * Used in subclasses that have no visibility of the field.
@@ -320,87 +323,64 @@ public class AbstractLinkedMap extends AbstractHashedMap 
implements OrderedMap {
      * @throws NullPointerException if the entry is null
      * @since Commons Collections 3.1
      */
-    protected LinkEntry entryAfter(LinkEntry entry) {
+    protected LinkEntry<K, V> entryAfter(LinkEntry<K, V> entry) {
         return entry.after;
     }
-    
-    //-----------------------------------------------------------------------
-    /**
-     * Gets an iterator over the map.
-     * Changes made to the iterator affect this map.
-     * <p>
-     * A MapIterator returns the keys in the map. It also provides convenient
-     * methods to get the key and value, and set the value.
-     * It avoids the need to create an entrySet/keySet/values object.
-     * 
-     * @return the map iterator
-     */
-    public MapIterator mapIterator() {
-        if (size == 0) {
-            return EmptyOrderedMapIterator.INSTANCE;
-        }
-        return new LinkMapIterator(this);
-    }
 
+    //-----------------------------------------------------------------------
     /**
-     * Gets a bidirectional iterator over the map.
-     * Changes made to the iterator affect this map.
-     * <p>
-     * A MapIterator returns the keys in the map. It also provides convenient
-     * methods to get the key and value, and set the value.
-     * It avoids the need to create an entrySet/keySet/values object.
-     * 
-     * @return the map iterator
+     * {@inheritDoc}
      */
-    public OrderedMapIterator orderedMapIterator() {
+    public OrderedMapIterator<K, V> mapIterator() {
         if (size == 0) {
-            return EmptyOrderedMapIterator.INSTANCE;
+            return EmptyOrderedMapIterator.<K, V>getInstance();
         }
-        return new LinkMapIterator(this);
+        return new LinkMapIterator<K, V>(this);
     }
 
     /**
      * MapIterator implementation.
      */
-    protected static class LinkMapIterator extends LinkIterator implements 
OrderedMapIterator {
-        
-        protected LinkMapIterator(AbstractLinkedMap parent) {
+    protected static class LinkMapIterator<K, V> extends LinkIterator<K, V> 
implements
+            OrderedMapIterator<K, V>, ResettableIterator<K> {
+
+        protected LinkMapIterator(AbstractLinkedMap<K, V> parent) {
             super(parent);
         }
 
-        public Object next() {
+        public K next() {
             return super.nextEntry().getKey();
         }
 
-        public Object previous() {
+        public K previous() {
             return super.previousEntry().getKey();
         }
 
-        public Object getKey() {
-            HashEntry current = currentEntry();
+        public K getKey() {
+            LinkEntry<K, V> current = currentEntry();
             if (current == null) {
                 throw new 
IllegalStateException(AbstractHashedMap.GETKEY_INVALID);
             }
             return current.getKey();
         }
 
-        public Object getValue() {
-            HashEntry current = currentEntry();
+        public V getValue() {
+            LinkEntry<K, V> current = currentEntry();
             if (current == null) {
                 throw new 
IllegalStateException(AbstractHashedMap.GETVALUE_INVALID);
             }
             return current.getValue();
         }
 
-        public Object setValue(Object value) {
-            HashEntry current = currentEntry();
+        public V setValue(V value) {
+            LinkEntry<K, V> current = currentEntry();
             if (current == null) {
                 throw new 
IllegalStateException(AbstractHashedMap.SETVALUE_INVALID);
             }
             return current.setValue(value);
         }
     }
-    
+
     //-----------------------------------------------------------------------  
  
     /**
      * Creates an entry set iterator.
@@ -408,27 +388,28 @@ public class AbstractLinkedMap extends AbstractHashedMap 
implements OrderedMap {
      * 
      * @return the entrySet iterator
      */
-    protected Iterator createEntrySetIterator() {
+    protected Iterator<Map.Entry<K, V>> createEntrySetIterator() {
         if (size() == 0) {
-            return EmptyOrderedIterator.INSTANCE;
+            return EmptyOrderedIterator.<Map.Entry<K, V>>getInstance();
         }
-        return new EntrySetIterator(this);
+        return new EntrySetIterator<K, V>(this);
     }
 
     /**
      * EntrySet iterator.
      */
-    protected static class EntrySetIterator extends LinkIterator {
-        
-        protected EntrySetIterator(AbstractLinkedMap parent) {
+    protected static class EntrySetIterator<K, V> extends LinkIterator<K, V> 
implements
+            OrderedIterator<Map.Entry<K, V>>, ResettableIterator<Map.Entry<K, 
V>> {
+
+        protected EntrySetIterator(AbstractLinkedMap<K, V> parent) {
             super(parent);
         }
 
-        public Object next() {
+        public Map.Entry<K, V> next() {
             return super.nextEntry();
         }
 
-        public Object previous() {
+        public Map.Entry<K, V> previous() {
             return super.previousEntry();
         }
     }
@@ -440,31 +421,33 @@ public class AbstractLinkedMap extends AbstractHashedMap 
implements OrderedMap {
      * 
      * @return the keySet iterator
      */
-    protected Iterator createKeySetIterator() {
+    protected Iterator<K> createKeySetIterator() {
         if (size() == 0) {
-            return EmptyOrderedIterator.INSTANCE;
+            return EmptyOrderedIterator.<K>getInstance();
         }
-        return new KeySetIterator(this);
+        return new KeySetIterator<K>(this);
     }
 
     /**
      * KeySet iterator.
      */
-    protected static class KeySetIterator extends EntrySetIterator {
+    protected static class KeySetIterator<K> extends LinkIterator<K, Object> 
implements
+            OrderedIterator<K>, ResettableIterator<K> {
         
-        protected KeySetIterator(AbstractLinkedMap parent) {
-            super(parent);
+        @SuppressWarnings("unchecked")
+        protected KeySetIterator(AbstractLinkedMap<K, ?> parent) {
+            super((AbstractLinkedMap<K, Object>) parent);
         }
 
-        public Object next() {
+        public K next() {
             return super.nextEntry().getKey();
         }
 
-        public Object previous() {
+        public K previous() {
             return super.previousEntry().getKey();
         }
     }
-    
+
     //-----------------------------------------------------------------------  
  
     /**
      * Creates a values iterator.
@@ -472,31 +455,33 @@ public class AbstractLinkedMap extends AbstractHashedMap 
implements OrderedMap {
      * 
      * @return the values iterator
      */
-    protected Iterator createValuesIterator() {
+    protected Iterator<V> createValuesIterator() {
         if (size() == 0) {
-            return EmptyOrderedIterator.INSTANCE;
+            return EmptyOrderedIterator.<V>getInstance();
         }
-        return new ValuesIterator(this);
+        return new ValuesIterator<V>(this);
     }
 
     /**
      * Values iterator.
      */
-    protected static class ValuesIterator extends LinkIterator {
-        
-        protected ValuesIterator(AbstractLinkedMap parent) {
-            super(parent);
+    protected static class ValuesIterator<V> extends LinkIterator<Object, V> 
implements
+            OrderedIterator<V>, ResettableIterator<V> {
+
+        @SuppressWarnings("unchecked")
+        protected ValuesIterator(AbstractLinkedMap<?, V> parent) {
+            super((AbstractLinkedMap<Object, V>) parent);
         }
 
-        public Object next() {
+        public V next() {
             return super.nextEntry().getValue();
         }
 
-        public Object previous() {
+        public V previous() {
             return super.previousEntry().getValue();
         }
     }
-    
+
     //-----------------------------------------------------------------------
     /**
      * LinkEntry that stores the data.
@@ -506,12 +491,12 @@ public class AbstractLinkedMap extends AbstractHashedMap 
implements OrderedMap {
      * The <code>entryXxx()</code> methods on <code>AbstractLinkedMap</code> 
exist
      * to provide the necessary access.
      */
-    protected static class LinkEntry extends HashEntry {
+    protected static class LinkEntry<K, V> extends HashEntry<K, V> {
         /** The entry before this one in the order */
-        protected LinkEntry before;
+        protected LinkEntry<K, V> before;
         /** The entry after this one in the order */
-        protected LinkEntry after;
-        
+        protected LinkEntry<K, V> after;
+
         /**
          * Constructs a new entry.
          * 
@@ -520,27 +505,26 @@ public class AbstractLinkedMap extends AbstractHashedMap 
implements OrderedMap {
          * @param key  the key
          * @param value  the value
          */
-        protected LinkEntry(HashEntry next, int hashCode, Object key, Object 
value) {
+        protected LinkEntry(HashEntry<K, V> next, int hashCode, Object key, V 
value) {
             super(next, hashCode, key, value);
         }
     }
-    
+
     /**
      * Base Iterator that iterates in link order.
      */
-    protected static abstract class LinkIterator
-            implements OrderedIterator, ResettableIterator {
-                
+    protected static abstract class LinkIterator<K, V> {
+
         /** The parent map */
-        protected final AbstractLinkedMap parent;
+        protected final AbstractLinkedMap<K, V> parent;
         /** The current (last returned) entry */
-        protected LinkEntry last;
+        protected LinkEntry<K, V> last;
         /** The next entry */
-        protected LinkEntry next;
+        protected LinkEntry<K, V> next;
         /** The modification count expected */
         protected int expectedModCount;
-        
-        protected LinkIterator(AbstractLinkedMap parent) {
+
+        protected LinkIterator(AbstractLinkedMap<K, V> parent) {
             super();
             this.parent = parent;
             this.next = parent.header.after;
@@ -550,12 +534,12 @@ public class AbstractLinkedMap extends AbstractHashedMap 
implements OrderedMap {
         public boolean hasNext() {
             return (next != parent.header);
         }
-        
+
         public boolean hasPrevious() {
             return (next.before != parent.header);
         }
 
-        protected LinkEntry nextEntry() {
+        protected LinkEntry<K, V> nextEntry() {
             if (parent.modCount != expectedModCount) {
                 throw new ConcurrentModificationException();
             }
@@ -567,11 +551,11 @@ public class AbstractLinkedMap extends AbstractHashedMap 
implements OrderedMap {
             return last;
         }
 
-        protected LinkEntry previousEntry() {
+        protected LinkEntry<K, V> previousEntry() {
             if (parent.modCount != expectedModCount) {
                 throw new ConcurrentModificationException();
             }
-            LinkEntry previous = next.before;
+            LinkEntry<K, V> previous = next.before;
             if (previous == parent.header)  {
                 throw new 
NoSuchElementException(AbstractHashedMap.NO_PREVIOUS_ENTRY);
             }
@@ -579,11 +563,11 @@ public class AbstractLinkedMap extends AbstractHashedMap 
implements OrderedMap {
             last = previous;
             return last;
         }
-        
-        protected LinkEntry currentEntry() {
+
+        protected LinkEntry<K, V> currentEntry() {
             return last;
         }
-        
+
         public void remove() {
             if (last == null) {
                 throw new 
IllegalStateException(AbstractHashedMap.REMOVE_INVALID);
@@ -595,7 +579,7 @@ public class AbstractLinkedMap extends AbstractHashedMap 
implements OrderedMap {
             last = null;
             expectedModCount = parent.modCount;
         }
-        
+
         public void reset() {
             last = null;
             next = parent.header.after;
@@ -604,10 +588,9 @@ public class AbstractLinkedMap extends AbstractHashedMap 
implements OrderedMap {
         public String toString() {
             if (last != null) {
                 return "Iterator[" + last.getKey() + "=" + last.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/AbstractOrderedMapDecorator.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/commons/collections/map/AbstractOrderedMapDecorator.java 
b/src/java/org/apache/commons/collections/map/AbstractOrderedMapDecorator.java
index 4a26fa4..4998a03 100644
--- 
a/src/java/org/apache/commons/collections/map/AbstractOrderedMapDecorator.java
+++ 
b/src/java/org/apache/commons/collections/map/AbstractOrderedMapDecorator.java
@@ -16,7 +16,6 @@
  */
 package org.apache.commons.collections.map;
 
-import org.apache.commons.collections.MapIterator;
 import org.apache.commons.collections.OrderedMap;
 import org.apache.commons.collections.OrderedMapIterator;
 
@@ -37,9 +36,8 @@ import org.apache.commons.collections.OrderedMapIterator;
  * 
  * @author Stephen Colebourne
  */
-public abstract class AbstractOrderedMapDecorator
-        extends AbstractMapDecorator
-        implements OrderedMap {
+public abstract class AbstractOrderedMapDecorator<K, V> extends 
AbstractMapDecorator<K, V>
+        implements OrderedMap<K, V> {
 
     /**
      * Constructor only used in deserialization, do not use otherwise.
@@ -55,7 +53,7 @@ public abstract class AbstractOrderedMapDecorator
      * @param map  the map to decorate, must not be null
      * @throws IllegalArgumentException if the collection is null
      */
-    public AbstractOrderedMapDecorator(OrderedMap map) {
+    public AbstractOrderedMapDecorator(OrderedMap<K, V> map) {
         super(map);
     }
 
@@ -64,33 +62,29 @@ public abstract class AbstractOrderedMapDecorator
      * 
      * @return the decorated map
      */
-    protected OrderedMap decorated() {
-        return (OrderedMap) super.decorated();
+    protected OrderedMap<K, V> decorated() {
+        return (OrderedMap<K, V>) super.decorated();
     }
 
     //-----------------------------------------------------------------------
-    public Object firstKey() {
+    public K firstKey() {
         return decorated().firstKey();
     }
 
-    public Object lastKey() {
+    public K lastKey() {
         return decorated().lastKey();
     }
 
-    public Object nextKey(Object key) {
+    public K nextKey(K key) {
         return decorated().nextKey(key);
     }
 
-    public Object previousKey(Object key) {
+    public K previousKey(K key) {
         return decorated().previousKey(key);
     }
 
-    public MapIterator mapIterator() {
+    public OrderedMapIterator<K, V> mapIterator() {
         return decorated().mapIterator();
     }
 
-    public OrderedMapIterator orderedMapIterator() {
-        return decorated().orderedMapIterator();
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/AbstractReferenceMap.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/commons/collections/map/AbstractReferenceMap.java 
b/src/java/org/apache/commons/collections/map/AbstractReferenceMap.java
index f5b31a2..60a0699 100644
--- a/src/java/org/apache/commons/collections/map/AbstractReferenceMap.java
+++ b/src/java/org/apache/commons/collections/map/AbstractReferenceMap.java
@@ -5,9 +5,9 @@
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -72,38 +72,61 @@ import 
org.apache.commons.collections.keyvalue.DefaultMapEntry;
  * <code>ResettableIterator</code> and calling <code>reset()</code>.
  * <p>
  * This implementation is not synchronized.
- * You can use {@link java.util.Collections#synchronizedMap} to 
+ * You can use {@link java.util.Collections#synchronizedMap} to
  * provide synchronized access to a <code>ReferenceMap</code>.
  *
  * @see java.lang.ref.Reference
  * @since Commons Collections 3.1 (extracted from ReferenceMap in 3.0)
  * @version $Revision$ $Date$
- * 
+ *
  * @author Paul Jack
  * @author Stephen Colebourne
  */
-public abstract class AbstractReferenceMap extends AbstractHashedMap {
+public abstract class AbstractReferenceMap<K, V> extends AbstractHashedMap<K, 
V> {
+
+    /**
+     * Reference type enum.
+     */
+    public static enum ReferenceStrength {
+        HARD(0), SOFT(1), WEAK(2);
+
+        /** value */
+        public final int value;
 
-    /** Constant indicating that hard references should be used */
-    public static final int HARD = 0;
+        /**
+         * Resolve enum from int.
+         * @param value
+         * @return ReferenceType
+         * @throws IllegalArgumentException if the specified value is invalid.
+         */
+        public static ReferenceStrength resolve(int value) {
+            switch (value) {
+            case 0:
+                return HARD;
+            case 1:
+                return SOFT;
+            case 2:
+                return WEAK;
+            default:
+                throw new IllegalArgumentException();
+            }
+        }
 
-    /** Constant indicating that soft references should be used */
-    public static final int SOFT = 1;
+        private ReferenceStrength(int value) {
+            this.value = value;
+        }
 
-    /** Constant indicating that weak references should be used */
-    public static final int WEAK = 2;
+    }
 
     /**
-     * The reference type for keys.  Must be HARD, SOFT, WEAK.
-     * @serial
+     * The reference type for keys.
      */
-    protected int keyType;
+    protected ReferenceStrength keyType;
 
     /**
-     * The reference type for values.  Must be HARD, SOFT, WEAK.
-     * @serial
+     * The reference type for values.
      */
-    protected int valueType;
+    protected ReferenceStrength valueType;
 
     /**
      * Should the value be automatically purged when the associated key has 
been collected?
@@ -114,7 +137,7 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
      * ReferenceQueue used to eliminate stale mappings.
      * See purge.
      */
-    private transient ReferenceQueue queue;
+    private transient ReferenceQueue<Object> queue;
 
     //-----------------------------------------------------------------------
     /**
@@ -134,15 +157,13 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
      *   must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
      * @param capacity  the initial capacity for the map
      * @param loadFactor  the load factor for the map
-     * @param purgeValues  should the value be automatically purged when the 
-     *   key is garbage collected 
+     * @param purgeValues  should the value be automatically purged when the
+     *   key is garbage collected
      */
     protected AbstractReferenceMap(
-            int keyType, int valueType, int capacity, 
+            ReferenceStrength keyType, ReferenceStrength valueType, int 
capacity,
             float loadFactor, boolean purgeValues) {
         super(capacity, loadFactor);
-        verify("keyType", keyType);
-        verify("valueType", valueType);
         this.keyType = keyType;
         this.valueType = valueType;
         this.purgeValues = purgeValues;
@@ -152,27 +173,13 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
      * Initialise this subclass during construction, cloning or 
deserialization.
      */
     protected void init() {
-        queue = new ReferenceQueue();
-    }
-
-    //-----------------------------------------------------------------------
-    /**
-     * Checks the type int is a valid value.
-     * 
-     * @param name  the name for error messages
-     * @param type  the type value to check
-     * @throws IllegalArgumentException if the value if invalid
-     */
-    private static void verify(String name, int type) {
-        if ((type < HARD) || (type > WEAK)) {
-            throw new IllegalArgumentException(name + " must be HARD, SOFT, 
WEAK.");
-        }
+        queue = new ReferenceQueue<Object>();
     }
 
     //-----------------------------------------------------------------------
     /**
      * Gets the size of the map.
-     * 
+     *
      * @return the size
      */
     public int size() {
@@ -182,7 +189,7 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
 
     /**
      * Checks whether the map is currently empty.
-     * 
+     *
      * @return true if the map is currently size zero
      */
     public boolean isEmpty() {
@@ -192,13 +199,13 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
 
     /**
      * Checks whether the map contains the specified key.
-     * 
+     *
      * @param key  the key to search for
      * @return true if the map contains the key
      */
     public boolean containsKey(Object key) {
         purgeBeforeRead();
-        Entry entry = getEntry(key);
+        Entry<K, V> entry = getEntry(key);
         if (entry == null) {
             return false;
         }
@@ -207,7 +214,7 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
 
     /**
      * Checks whether the map contains the specified value.
-     * 
+     *
      * @param value  the value to search for
      * @return true if the map contains the value
      */
@@ -221,13 +228,13 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
 
     /**
      * Gets the value mapped to the key specified.
-     * 
+     *
      * @param key  the key
      * @return the mapped value, null if no match
      */
-    public Object get(Object key) {
+    public V get(Object key) {
         purgeBeforeRead();
-        Entry entry = getEntry(key);
+        Entry<K, V> entry = getEntry(key);
         if (entry == null) {
             return null;
         }
@@ -238,13 +245,13 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
     /**
      * Puts a key-value mapping into this map.
      * Neither the key nor the value may be null.
-     * 
+     *
      * @param key  the key to add, must not be null
      * @param value  the value to add, must not be null
      * @return the value previously mapped to this key, null if none
      * @throws NullPointerException if either the key or value is null
      */
-    public Object put(Object key, Object value) {
+    public V put(K key, V value) {
         if (key == null) {
             throw new NullPointerException("null keys not allowed");
         }
@@ -255,14 +262,14 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
         purgeBeforeWrite();
         return super.put(key, value);
     }
-    
+
     /**
      * Removes the specified mapping from this map.
-     * 
+     *
      * @param key  the mapping to remove
      * @return the value mapped to the removed key, null if key not in map
      */
-    public Object remove(Object key) {
+    public V remove(Object key) {
         if (key == null) {
             return null;
         }
@@ -282,11 +289,11 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
     /**
      * Gets a MapIterator over the reference map.
      * The iterator only returns valid key/value pairs.
-     * 
+     *
      * @return a map iterator
      */
-    public MapIterator mapIterator() {
-        return new ReferenceMapIterator(this);
+    public MapIterator<K, V> mapIterator() {
+        return new ReferenceMapIterator<K, V>(this);
     }
 
     /**
@@ -296,9 +303,9 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
      *
      * @return a set view of this map's entries
      */
-    public Set entrySet() {
+    public Set<Map.Entry<K, V>> entrySet() {
         if (entrySet == null) {
-            entrySet = new ReferenceEntrySet(this);
+            entrySet = new ReferenceEntrySet<K, V>(this);
         }
         return entrySet;
     }
@@ -308,9 +315,9 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
      *
      * @return a set view of this map's keys
      */
-    public Set keySet() {
+    public Set<K> keySet() {
         if (keySet == null) {
-            keySet = new ReferenceKeySet(this);
+            keySet = new ReferenceKeySet<K>(this);
         }
         return keySet;
     }
@@ -320,9 +327,9 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
      *
      * @return a set view of this map's values
      */
-    public Collection values() {
+    public Collection<V> values() {
         if (values == null) {
-            values = new ReferenceValues(this);
+            values = new ReferenceValues<V>(this);
         }
         return values;
     }
@@ -355,7 +362,7 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
      * background thread.
      */
     protected void purge() {
-        Reference ref = queue.poll();
+        Reference<?> ref = queue.poll();
         while (ref != null) {
             purge(ref);
             ref = queue.poll();
@@ -364,19 +371,19 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
 
     /**
      * Purges the specified reference.
-     * 
+     *
      * @param ref  the reference to purge
      */
-    protected void purge(Reference ref) {
+    protected void purge(Reference<?> ref) {
         // The hashCode of the reference is the hashCode of the
-        // mapping key, even if the reference refers to the 
+        // mapping key, even if the reference refers to the
         // mapping value...
         int hash = ref.hashCode();
         int index = hashIndex(hash, data.length);
-        HashEntry previous = null;
-        HashEntry entry = data[index];
+        HashEntry<K, V> previous = null;
+        HashEntry<K, V> entry = data[index];
         while (entry != null) {
-            if (((ReferenceEntry) entry).purge(ref)) {
+            if (((ReferenceEntry<K, V>) entry).purge(ref)) {
                 if (previous == null) {
                     data[index] = entry.next;
                 } else {
@@ -394,93 +401,93 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
     //-----------------------------------------------------------------------
     /**
      * Gets the entry mapped to the key specified.
-     * 
+     *
      * @param key  the key
      * @return the entry, null if no match
      */
-    protected HashEntry getEntry(Object key) {
+    protected HashEntry<K, V> getEntry(Object key) {
         if (key == null) {
             return null;
-        } else {
-            return super.getEntry(key);
         }
+        return super.getEntry(key);
     }
 
     /**
      * Gets the hash code for a MapEntry.
      * Subclasses can override this, for example to use the identityHashCode.
-     * 
+     *
      * @param key  the key to get a hash code for, may be null
      * @param value  the value to get a hash code for, may be null
      * @return the hash code, as per the MapEntry specification
      */
     protected int hashEntry(Object key, Object value) {
         return (key == null ? 0 : key.hashCode()) ^
-               (value == null ? 0 : value.hashCode()); 
+               (value == null ? 0 : value.hashCode());
     }
-    
+
     /**
      * Compares two keys, in internal converted form, to see if they are equal.
      * <p>
      * This implementation converts the key from the entry to a real reference
      * before comparison.
-     * 
+     *
      * @param key1  the first key to compare passed in from outside
      * @param key2  the second key extracted from the entry via 
<code>entry.key</code>
      * @return true if equal
      */
+    @SuppressWarnings("unchecked")
     protected boolean isEqualKey(Object key1, Object key2) {
-        key2 = (keyType > HARD ? ((Reference) key2).get() : key2);
+        key2 = (keyType == ReferenceStrength.HARD ? key2 : ((Reference<K>) 
key2).get());
         return (key1 == key2 || key1.equals(key2));
     }
-    
+
     /**
      * Creates a ReferenceEntry instead of a HashEntry.
-     * 
+     *
      * @param next  the next entry in sequence
      * @param hashCode  the hash code to use
      * @param key  the key to store
      * @param value  the value to store
      * @return the newly created entry
      */
-    protected HashEntry createEntry(HashEntry next, int hashCode, Object key, 
Object value) {
-        return new ReferenceEntry(this, next, hashCode, key, value);
+    protected ReferenceEntry<K, V> createEntry(HashEntry<K, V> next, int 
hashCode, K key, V value) {
+        return new ReferenceEntry<K, V>(this, next, hashCode, key, value);
     }
 
     /**
      * Creates an entry set iterator.
-     * 
+     *
      * @return the entrySet iterator
      */
-    protected Iterator createEntrySetIterator() {
-        return new ReferenceEntrySetIterator(this);
+    protected Iterator<Map.Entry<K, V>> createEntrySetIterator() {
+        return new ReferenceEntrySetIterator<K, V>(this);
     }
 
     /**
      * Creates an key set iterator.
-     * 
+     *
      * @return the keySet iterator
      */
-    protected Iterator createKeySetIterator() {
-        return new ReferenceKeySetIterator(this);
+    protected Iterator<K> createKeySetIterator() {
+        return new ReferenceKeySetIterator<K>(this);
     }
 
     /**
      * Creates an values iterator.
-     * 
+     *
      * @return the values iterator
      */
-    protected Iterator createValuesIterator() {
-        return new ReferenceValuesIterator(this);
+    protected Iterator<V> createValuesIterator() {
+        return new ReferenceValuesIterator<V>(this);
     }
 
     //-----------------------------------------------------------------------
     /**
      * EntrySet implementation.
      */
-    static class ReferenceEntrySet extends EntrySet {
-        
-        protected ReferenceEntrySet(AbstractHashedMap parent) {
+    static class ReferenceEntrySet<K, V> extends EntrySet<K, V> {
+
+        protected ReferenceEntrySet(AbstractHashedMap<K, V> parent) {
             super(parent);
         }
 
@@ -488,13 +495,11 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
             return toArray(new Object[0]);
         }
 
-        public Object[] toArray(Object[] arr) {
+        public <T> T[] toArray(T[] arr) {
             // special implementation to handle disappearing entries
-            ArrayList list = new ArrayList();
-            Iterator iterator = iterator();
-            while (iterator.hasNext()) {
-                Entry e = (Entry) iterator.next();
-                list.add(new DefaultMapEntry(e.getKey(), e.getValue()));
+            ArrayList<Map.Entry<K, V>> list = new ArrayList<Map.Entry<K, V>>();
+            for (Map.Entry<K, V> entry : this) {
+                list.add(new DefaultMapEntry<K, V>(entry));
             }
             return list.toArray(arr);
         }
@@ -504,9 +509,9 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
     /**
      * KeySet implementation.
      */
-    static class ReferenceKeySet extends KeySet {
-        
-        protected ReferenceKeySet(AbstractHashedMap parent) {
+    static class ReferenceKeySet<K> extends KeySet<K> {
+
+        protected ReferenceKeySet(AbstractHashedMap<K, ?> parent) {
             super(parent);
         }
 
@@ -514,11 +519,11 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
             return toArray(new Object[0]);
         }
 
-        public Object[] toArray(Object[] arr) {
+        public <T> T[] toArray(T[] arr) {
             // special implementation to handle disappearing keys
-            List list = new ArrayList(parent.size());
-            for (Iterator it = iterator(); it.hasNext(); ) {
-                list.add(it.next());
+            List<K> list = new ArrayList<K>(parent.size());
+            for (K key : this) {
+                list.add(key);
             }
             return list.toArray(arr);
         }
@@ -528,9 +533,9 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
     /**
      * Values implementation.
      */
-    static class ReferenceValues extends Values {
-        
-        protected ReferenceValues(AbstractHashedMap parent) {
+    static class ReferenceValues<V> extends Values<V> {
+
+        protected ReferenceValues(AbstractHashedMap<?, V> parent) {
             super(parent);
         }
 
@@ -538,11 +543,11 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
             return toArray(new Object[0]);
         }
 
-        public Object[] toArray(Object[] arr) {
+        public <T> T[] toArray(T[] arr) {
             // special implementation to handle disappearing values
-            List list = new ArrayList(parent.size());
-            for (Iterator it = iterator(); it.hasNext(); ) {
-                list.add(it.next());
+            List<V> list = new ArrayList<V>(parent.size());
+            for (V value : this) {
+                list.add(value);
             }
             return list.toArray(arr);
         }
@@ -554,23 +559,23 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
      * <p>
      * If getKey() or getValue() returns null, it means
      * the mapping is stale and should be removed.
-     * 
+     *
      * @since Commons Collections 3.1
      */
-    protected static class ReferenceEntry extends HashEntry {
+    protected static class ReferenceEntry<K, V> extends HashEntry<K, V> {
         /** The parent map */
-        protected final AbstractReferenceMap parent;
+        protected final AbstractReferenceMap<K, V> parent;
 
         /**
          * Creates a new entry object for the ReferenceMap.
-         * 
+         *
          * @param parent  the parent map
          * @param next  the next entry in the hash bucket
          * @param hashCode  the hash code of the key
          * @param key  the key
          * @param value  the value
          */
-        public ReferenceEntry(AbstractReferenceMap parent, HashEntry next, int 
hashCode, Object key, Object value) {
+        public ReferenceEntry(AbstractReferenceMap<K, V> parent, HashEntry<K, 
V> next, int hashCode, K key, V value) {
             super(next, hashCode, null, null);
             this.parent = parent;
             this.key = toReference(parent.keyType, key, hashCode);
@@ -580,33 +585,36 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
         /**
          * Gets the key from the entry.
          * This method dereferences weak and soft keys and thus may return 
null.
-         * 
+         *
          * @return the key, which may be null if it was garbage collected
          */
-        public Object getKey() {
-            return (parent.keyType > HARD) ? ((Reference) key).get() : key;
+        @SuppressWarnings("unchecked")
+        public K getKey() {
+            return (K) ((parent.keyType == ReferenceStrength.HARD) ? key : 
((Reference<K>) key).get());
         }
 
         /**
          * Gets the value from the entry.
          * This method dereferences weak and soft value and thus may return 
null.
-         * 
+         *
          * @return the value, which may be null if it was garbage collected
          */
-        public Object getValue() {
-            return (parent.valueType > HARD) ? ((Reference) value).get() : 
value;
+        @SuppressWarnings("unchecked")
+        public V getValue() {
+            return (V) ((parent.valueType == ReferenceStrength.HARD) ? value : 
((Reference<V>) value).get());
         }
 
         /**
          * Sets the value of the entry.
-         * 
+         *
          * @param obj  the object to store
          * @return the previous value
          */
-        public Object setValue(Object obj) {
-            Object old = getValue();
-            if (parent.valueType > HARD) {
-                ((Reference)value).clear();
+        @SuppressWarnings("unchecked")
+        public V setValue(V obj) {
+            V old = getValue();
+            if (parent.valueType != ReferenceStrength.HARD) {
+                ((Reference<V>) value).clear();
             }
             value = toReference(parent.valueType, obj, hashCode);
             return old;
@@ -617,10 +625,11 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
          * <p>
          * This implementation uses <code>isEqualKey</code> and
          * <code>isEqualValue</code> on the main map for comparison.
-         * 
+         *
          * @param obj  the other map entry to compare to
          * @return true if equal, false if not
          */
+        @SuppressWarnings("unchecked")
         public boolean equals(Object obj) {
             if (obj == this) {
                 return true;
@@ -628,7 +637,7 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
             if (obj instanceof Map.Entry == false) {
                 return false;
             }
-            
+
             Map.Entry entry = (Map.Entry)obj;
             Object entryKey = entry.getKey();  // convert to hard reference
             Object entryValue = entry.getValue();  // convert to hard reference
@@ -645,7 +654,7 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
          * Gets the hashcode of the entry using temporary hard references.
          * <p>
          * This implementation uses <code>hashEntry</code> on the main map.
-         * 
+         *
          * @return the hashcode of the entry
          */
         public int hashCode() {
@@ -662,13 +671,17 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
          *    this number might be different from referent.hashCode() if
          *    the referent represents a value and not a key
          */
-        protected Object toReference(int type, Object referent, int hash) {
-            switch (type) {
-                case HARD: return referent;
-                case SOFT: return new SoftRef(hash, referent, parent.queue);
-                case WEAK: return new WeakRef(hash, referent, parent.queue);
-                default: throw new Error();
+        protected <T> Object toReference(ReferenceStrength type, T referent, 
int hash) {
+            if (type == ReferenceStrength.HARD) {
+                return referent;
             }
+            if (type == ReferenceStrength.SOFT) {
+                return new SoftRef<T>(hash, referent, parent.queue);
+            }
+            if (type == ReferenceStrength.WEAK) {
+                return new WeakRef<T>(hash, referent, parent.queue);
+            }
+            throw new Error();
         }
 
         /**
@@ -676,15 +689,15 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
          * @param ref  the reference to purge
          * @return true or false
          */
-        boolean purge(Reference ref) {
-            boolean r = (parent.keyType > HARD) && (key == ref);
-            r = r || ((parent.valueType > HARD) && (value == ref));
+        boolean purge(Reference<?> ref) {
+            boolean r = (parent.keyType != ReferenceStrength.HARD) && (key == 
ref);
+            r = r || ((parent.valueType != ReferenceStrength.HARD) && (value 
== ref));
             if (r) {
-                if (parent.keyType > HARD) {
-                    ((Reference)key).clear();
+                if (parent.keyType != ReferenceStrength.HARD) {
+                    ((Reference<?>) key).clear();
                 }
-                if (parent.valueType > HARD) {
-                    ((Reference)value).clear();
+                if (parent.valueType != ReferenceStrength.HARD) {
+                    ((Reference<?>) value).clear();
                 } else if (parent.purgeValues) {
                     value = null;
                 }
@@ -694,36 +707,36 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
 
         /**
          * Gets the next entry in the bucket.
-         * 
+         *
          * @return the next entry in the bucket
          */
-        protected ReferenceEntry next() {
-            return (ReferenceEntry) next;
+        protected ReferenceEntry<K, V> next() {
+            return (ReferenceEntry<K, V>) next;
         }
     }
 
     //-----------------------------------------------------------------------
     /**
-     * The EntrySet iterator.
+     * Base iterator class.
      */
-    static class ReferenceEntrySetIterator implements Iterator {
+    static class ReferenceBaseIterator<K, V> {
         /** The parent map */
-        final AbstractReferenceMap parent;
-        
+        final AbstractReferenceMap<K, V> parent;
+
         // These fields keep track of where we are in the table.
         int index;
-        ReferenceEntry entry;
-        ReferenceEntry previous;
+        ReferenceEntry<K, V> entry;
+        ReferenceEntry<K, V> previous;
 
         // These Object fields provide hard references to the
         // current and next entry; this assures that if hasNext()
         // returns true, next() will actually return a valid element.
-        Object nextKey, nextValue;
-        Object currentKey, currentValue;
+        K currentKey, nextKey;
+        V currentValue, nextValue;
 
         int expectedModCount;
 
-        public ReferenceEntrySetIterator(AbstractReferenceMap parent) {
+        public ReferenceBaseIterator(AbstractReferenceMap<K, V> parent) {
             super();
             this.parent = parent;
             index = (parent.size() != 0 ? parent.data.length : 0);
@@ -735,11 +748,11 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
         public boolean hasNext() {
             checkMod();
             while (nextNull()) {
-                ReferenceEntry e = entry;
+                ReferenceEntry<K, V> e = entry;
                 int i = index;
                 while ((e == null) && (i > 0)) {
                     i--;
-                    e = (ReferenceEntry) parent.data[i];
+                    e = (ReferenceEntry<K, V>) parent.data[i];
                 }
                 entry = e;
                 index = i;
@@ -767,7 +780,7 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
             return (nextKey == null) || (nextValue == null);
         }
 
-        protected ReferenceEntry nextEntry() {    
+        protected ReferenceEntry<K, V> nextEntry() {
             checkMod();
             if (nextNull() && !hasNext()) {
                 throw new NoSuchElementException();
@@ -781,14 +794,10 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
             return previous;
         }
 
-        protected ReferenceEntry currentEntry() {
+        protected ReferenceEntry<K, V> currentEntry() {
             checkMod();
             return previous;
         }
-        
-        public Object next() {
-            return nextEntry();
-        }
 
         public void remove() {
             checkMod();
@@ -804,15 +813,31 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
     }
 
     /**
-     * The keySet iterator.
+     * The EntrySet iterator.
      */
-    static class ReferenceKeySetIterator extends ReferenceEntrySetIterator {
-        
-        ReferenceKeySetIterator(AbstractReferenceMap parent) {
+    static class ReferenceEntrySetIterator<K, V> extends 
ReferenceBaseIterator<K, V> implements Iterator<Map.Entry<K, V>> {
+
+        public ReferenceEntrySetIterator(AbstractReferenceMap<K, V> parent) {
             super(parent);
         }
-        
-        public Object next() {
+
+        public Map.Entry<K, V> next() {
+            return nextEntry();
+        }
+
+    }
+
+    /**
+     * The keySet iterator.
+     */
+    static class ReferenceKeySetIterator<K> extends ReferenceBaseIterator<K, 
Object> implements Iterator<K> {
+
+        @SuppressWarnings("unchecked")
+        ReferenceKeySetIterator(AbstractReferenceMap<K, ?> parent) {
+            super((AbstractReferenceMap<K, Object>) parent);
+        }
+
+        public K next() {
             return nextEntry().getKey();
         }
     }
@@ -820,13 +845,14 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
     /**
      * The values iterator.
      */
-    static class ReferenceValuesIterator extends ReferenceEntrySetIterator {
-        
-        ReferenceValuesIterator(AbstractReferenceMap parent) {
-            super(parent);
+    static class ReferenceValuesIterator<V> extends 
ReferenceBaseIterator<Object, V> implements Iterator<V> {
+
+        @SuppressWarnings("unchecked")
+        ReferenceValuesIterator(AbstractReferenceMap<?, V> parent) {
+            super((AbstractReferenceMap<Object, V>) parent);
         }
-        
-        public Object next() {
+
+        public V next() {
             return nextEntry().getValue();
         }
     }
@@ -834,41 +860,41 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
     /**
      * The MapIterator implementation.
      */
-    static class ReferenceMapIterator extends ReferenceEntrySetIterator 
implements MapIterator {
-        
-        protected ReferenceMapIterator(AbstractReferenceMap parent) {
+    static class ReferenceMapIterator<K, V> extends ReferenceBaseIterator<K, 
V> implements MapIterator<K, V> {
+
+        protected ReferenceMapIterator(AbstractReferenceMap<K, V> parent) {
             super(parent);
         }
 
-        public Object next() {
+        public K next() {
             return nextEntry().getKey();
         }
 
-        public Object getKey() {
-            HashEntry current = currentEntry();
+        public K getKey() {
+            HashEntry<K, V> current = currentEntry();
             if (current == null) {
                 throw new 
IllegalStateException(AbstractHashedMap.GETKEY_INVALID);
             }
             return current.getKey();
         }
 
-        public Object getValue() {
-            HashEntry current = currentEntry();
+        public V getValue() {
+            HashEntry<K, V> current = currentEntry();
             if (current == null) {
                 throw new 
IllegalStateException(AbstractHashedMap.GETVALUE_INVALID);
             }
             return current.getValue();
         }
 
-        public Object setValue(Object value) {
-            HashEntry current = currentEntry();
+        public V setValue(V value) {
+            HashEntry<K, V> current = currentEntry();
             if (current == null) {
                 throw new 
IllegalStateException(AbstractHashedMap.SETVALUE_INVALID);
             }
             return current.setValue(value);
         }
     }
-    
+
     //-----------------------------------------------------------------------
     // These two classes store the hashCode of the key of
     // of the mapping, so that after they're dequeued a quick
@@ -877,11 +903,11 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
     /**
      * A soft reference holder.
      */
-    static class SoftRef extends SoftReference {
+    static class SoftRef<T> extends SoftReference<T> {
         /** the hashCode of the key (even if the reference points to a value) 
*/
         private int hash;
 
-        public SoftRef(int hash, Object r, ReferenceQueue q) {
+        public SoftRef(int hash, T r, ReferenceQueue<? super T> q) {
             super(r, q);
             this.hash = hash;
         }
@@ -894,11 +920,11 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
     /**
      * A weak reference holder.
      */
-    static class WeakRef extends WeakReference {
+    static class WeakRef<T> extends WeakReference<T> {
         /** the hashCode of the key (even if the reference points to a value) 
*/
         private int hash;
 
-        public WeakRef(int hash, Object r, ReferenceQueue q) {
+        public WeakRef(int hash, T r, ReferenceQueue<? super T> q) {
             super(r, q);
             this.hash = hash;
         }
@@ -924,16 +950,16 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
      * Subclasses may override if they have a specific field that must be 
present
      * on read before this implementation will work. Generally, the read 
determines
      * what must be serialized here, if anything.
-     * 
+     *
      * @param out  the output stream
      */
     protected void doWriteObject(ObjectOutputStream out) throws IOException {
-        out.writeInt(keyType);
-        out.writeInt(valueType);
+        out.writeInt(keyType.value);
+        out.writeInt(valueType.value);
         out.writeBoolean(purgeValues);
         out.writeFloat(loadFactor);
         out.writeInt(data.length);
-        for (MapIterator it = mapIterator(); it.hasNext();) {
+        for (MapIterator<K, V> it = mapIterator(); it.hasNext();) {
             out.writeObject(it.next());
             out.writeObject(it.getValue());
         }
@@ -955,23 +981,24 @@ public abstract class AbstractReferenceMap extends 
AbstractHashedMap {
      * <p>
      * Subclasses may override if the subclass has a specific field that must 
be present
      * before <code>put()</code> or <code>calculateThreshold()</code> will 
work correctly.
-     * 
+     *
      * @param in  the input stream
      */
+    @SuppressWarnings("unchecked")
     protected void doReadObject(ObjectInputStream in) throws IOException, 
ClassNotFoundException {
-        this.keyType = in.readInt();
-        this.valueType = in.readInt();
+        this.keyType = ReferenceStrength.resolve(in.readInt());
+        this.valueType = ReferenceStrength.resolve(in.readInt());
         this.purgeValues = in.readBoolean();
         this.loadFactor = in.readFloat();
         int capacity = in.readInt();
         init();
         data = new HashEntry[capacity];
         while (true) {
-            Object key = in.readObject();
+            K key = (K) in.readObject();
             if (key == null) {
                 break;
             }
-            Object value = in.readObject();
+            V value = (V) in.readObject();
             put(key, value);
         }
         threshold = calculateThreshold(data.length, loadFactor);

http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/AbstractSortedMapDecorator.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/commons/collections/map/AbstractSortedMapDecorator.java 
b/src/java/org/apache/commons/collections/map/AbstractSortedMapDecorator.java
index eae1600..7c9a35b 100644
--- 
a/src/java/org/apache/commons/collections/map/AbstractSortedMapDecorator.java
+++ 
b/src/java/org/apache/commons/collections/map/AbstractSortedMapDecorator.java
@@ -38,9 +38,8 @@ import java.util.SortedMap;
  * 
  * @author Stephen Colebourne
  */
-public abstract class AbstractSortedMapDecorator<K, V>
-        extends AbstractMapDecorator<K, V>
-        implements SortedMap<K, V> {
+public abstract class AbstractSortedMapDecorator<K, V> extends 
AbstractMapDecorator<K, V> implements
+        SortedMap<K, V> {
 
     /**
      * Constructor only used in deserialization, do not use otherwise.

http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/CaseInsensitiveMap.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/commons/collections/map/CaseInsensitiveMap.java 
b/src/java/org/apache/commons/collections/map/CaseInsensitiveMap.java
index 7d5a18c..05f4206 100644
--- a/src/java/org/apache/commons/collections/map/CaseInsensitiveMap.java
+++ b/src/java/org/apache/commons/collections/map/CaseInsensitiveMap.java
@@ -57,7 +57,7 @@ import java.util.Map;
  *
  * @author Commons-Collections team
  */
-public class CaseInsensitiveMap extends AbstractHashedMap implements 
Serializable, Cloneable {
+public class CaseInsensitiveMap<K, V> extends AbstractHashedMap<K, V> 
implements Serializable, Cloneable {
 
     /** Serialisation version */
     private static final long serialVersionUID = -7074655917369299456L;
@@ -102,7 +102,7 @@ public class CaseInsensitiveMap extends AbstractHashedMap 
implements Serializabl
      * @param map  the map to copy
      * @throws NullPointerException if the map is null
      */
-    public CaseInsensitiveMap(Map map) {
+    public CaseInsensitiveMap(Map<K, V> map) {
         super(map);
     }
 
@@ -119,9 +119,8 @@ public class CaseInsensitiveMap extends AbstractHashedMap 
implements Serializabl
     protected Object convertKey(Object key) {
         if (key != null) {
             return key.toString().toLowerCase();
-        } else {
-            return AbstractHashedMap.NULL;
         }
+        return AbstractHashedMap.NULL;
     }   
 
     //-----------------------------------------------------------------------
@@ -130,8 +129,8 @@ public class CaseInsensitiveMap extends AbstractHashedMap 
implements Serializabl
      *
      * @return a shallow clone
      */
-    public Object clone() {
-        return super.clone();
+    public CaseInsensitiveMap<K, V> clone() {
+        return (CaseInsensitiveMap<K, V>) super.clone();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/CompositeMap.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/commons/collections/map/CompositeMap.java 
b/src/java/org/apache/commons/collections/map/CompositeMap.java
index b806c62..264d7ec 100644
--- a/src/java/org/apache/commons/collections/map/CompositeMap.java
+++ b/src/java/org/apache/commons/collections/map/CompositeMap.java
@@ -5,9 +5,9 @@
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -17,7 +17,6 @@
 package org.apache.commons.collections.map;
 
 import java.util.Collection;
-import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 
@@ -35,7 +34,7 @@ import org.apache.commons.collections.set.CompositeSet;
  * <strong>Note that CompositeMap is not synchronized and is not 
thread-safe.</strong>
  * If you wish to use this map from multiple threads concurrently, you must use
  * appropriate synchronization. The simplest approach is to wrap this map
- * using {@link java.util.Collections#synchronizedMap(Map)}. This class may 
throw 
+ * using {@link java.util.Collections#synchronizedMap(Map)}. This class may 
throw
  * exceptions when accessed by concurrent threads without synchronization.
  *
  * @since Commons Collections 3.0
@@ -43,62 +42,66 @@ import org.apache.commons.collections.set.CompositeSet;
  *
  * @author Brian McCallister
  */
-public class CompositeMap implements Map {
+public class CompositeMap<K, V> implements Map<K, V> {
 
     /** Array of all maps in the composite */
-    private Map[] composite;
+    private Map<K, V>[] composite;
 
     /** Handle mutation operations */
-    private MapMutator mutator;
+    private MapMutator<K, V> mutator;
 
     /**
      * Create a new, empty, CompositeMap.
      */
+    @SuppressWarnings("unchecked")
     public CompositeMap() {
-        this(new Map[]{}, null);
+        this(new Map[] {}, null);
     }
 
     /**
      * Create a new CompositeMap with two composited Map instances.
-     * 
+     *
      * @param one  the first Map to be composited
      * @param two  the second Map to be composited
      * @throws IllegalArgumentException if there is a key collision
      */
-    public CompositeMap(Map one, Map two) {
-        this(new Map[]{one, two}, null);
+    @SuppressWarnings("unchecked")
+    public CompositeMap(Map<K, V> one, Map<K, V> two) {
+        this(new Map[] { one, two }, null);
     }
 
     /**
      * Create a new CompositeMap with two composited Map instances.
-     * 
+     *
      * @param one  the first Map to be composited
      * @param two  the second Map to be composited
      * @param mutator  MapMutator to be used for mutation operations
      */
-    public CompositeMap(Map one, Map two, MapMutator mutator) {
-        this(new Map[]{one, two}, mutator);
+    @SuppressWarnings("unchecked")
+    public CompositeMap(Map<K, V> one, Map<K, V> two, MapMutator<K, V> 
mutator) {
+        this(new Map[] { one, two }, mutator);
     }
 
     /**
      * Create a new CompositeMap which composites all of the Map instances in 
the
      * argument. It copies the argument array, it does not use it directly.
-     * 
+     *
      * @param composite  the Maps to be composited
      * @throws IllegalArgumentException if there is a key collision
      */
-    public CompositeMap(Map[] composite) {
+    public CompositeMap(Map<K, V>[] composite) {
         this(composite, null);
     }
 
     /**
      * Create a new CompositeMap which composites all of the Map instances in 
the
      * argument. It copies the argument array, it does not use it directly.
-     * 
+     *
      * @param composite  Maps to be composited
      * @param mutator  MapMutator to be used for mutation operations
      */
-    public CompositeMap(Map[] composite, MapMutator mutator) {
+    @SuppressWarnings("unchecked")
+    public CompositeMap(Map<K, V>[] composite, MapMutator<K, V> mutator) {
         this.mutator = mutator;
         this.composite = new Map[0];
         for (int i = composite.length - 1; i >= 0; --i) {
@@ -109,13 +112,13 @@ public class CompositeMap implements Map {
     //-----------------------------------------------------------------------
     /**
      * Specify the MapMutator to be used by mutation operations.
-     * 
+     *
      * @param mutator  the MapMutator to be used for mutation delegation
      */
-    public void setMutator(MapMutator mutator) {
+    public void setMutator(MapMutator<K, V> mutator) {
         this.mutator = mutator;
     }
-    
+
     /**
      * Add an additional Map to the composite.
      *
@@ -123,35 +126,35 @@ public class CompositeMap implements Map {
      * @throws IllegalArgumentException if there is a key collision and there 
is no
      *         MapMutator set to handle it.
      */
-    public synchronized void addComposited(Map map) throws 
IllegalArgumentException {
+    @SuppressWarnings("unchecked")
+    public synchronized void addComposited(Map<K, V> map) throws 
IllegalArgumentException {
         for (int i = composite.length - 1; i >= 0; --i) {
-            Collection intersect = 
CollectionUtils.intersection(this.composite[i].keySet(), map.keySet());
+            Collection<K> intersect = 
CollectionUtils.intersection(this.composite[i].keySet(), map.keySet());
             if (intersect.size() != 0) {
                 if (this.mutator == null) {
                     throw new IllegalArgumentException("Key collision adding 
Map to CompositeMap");
                 }
-                else {
-                    this.mutator.resolveCollision(this, this.composite[i], 
map, intersect);
-                }
+                this.mutator.resolveCollision(this, this.composite[i], map, 
intersect);
             }
         }
-        Map[] temp = new Map[this.composite.length + 1];
+        Map<K, V>[] temp = new Map[this.composite.length + 1];
         System.arraycopy(this.composite, 0, temp, 0, this.composite.length);
         temp[temp.length - 1] = map;
         this.composite = temp;
     }
-    
+
     /**
      * Remove a Map from the composite.
      *
      * @param map  the Map to be removed from the composite
      * @return The removed Map or <code>null</code> if map is not in the 
composite
      */
-    public synchronized Map removeComposited(Map map) {
+    @SuppressWarnings("unchecked")
+    public synchronized Map<K, V> removeComposited(Map<K, V> map) {
         int size = this.composite.length;
         for (int i = 0; i < size; ++i) {
             if (this.composite[i].equals(map)) {
-                Map[] temp = new Map[size - 1];
+                Map<K, V>[] temp = new Map[size - 1];
                 System.arraycopy(this.composite, 0, temp, 0, i);
                 System.arraycopy(this.composite, i + 1, temp, i, size - i - 1);
                 this.composite = temp;
@@ -161,7 +164,7 @@ public class CompositeMap implements Map {
         return null;
     }
 
-    //-----------------------------------------------------------------------  
  
+    //-----------------------------------------------------------------------
     /**
      * Calls <code>clear()</code> on all composited Maps.
      *
@@ -172,7 +175,7 @@ public class CompositeMap implements Map {
             this.composite[i].clear();
         }
     }
-    
+
     /**
      * Returns <tt>true</tt> if this map contains a mapping for the specified
      * key.  More formally, returns <tt>true</tt> if and only if
@@ -197,7 +200,7 @@ public class CompositeMap implements Map {
         }
         return false;
     }
-    
+
     /**
      * Returns <tt>true</tt> if this map maps one or more keys to the
      * specified value.  More formally, returns <tt>true</tt> if and only if
@@ -222,7 +225,7 @@ public class CompositeMap implements Map {
         }
         return false;
     }
-    
+
     /**
      * Returns a set view of the mappings contained in this map.  Each element
      * in the returned set is a <code>Map.Entry</code>.  The set is backed by 
the
@@ -240,14 +243,14 @@ public class CompositeMap implements Map {
      * @see CompositeSet
      * @return a set view of the mappings contained in this map.
      */
-    public Set entrySet() {
-        CompositeSet entries = new CompositeSet();
-        for (int i = this.composite.length - 1; i >= 0; --i) {
-            entries.addComposited(this.composite[i].entrySet());
+    public Set<Map.Entry<K, V>> entrySet() {
+        CompositeSet<Map.Entry<K, V>> entries = new 
CompositeSet<Map.Entry<K,V>>();
+        for (int i = composite.length - 1; i >= 0; --i) {
+            entries.addComposited((Collection<Map.Entry<K, V>>) 
composite[i].entrySet());
         }
         return entries;
     }
-    
+
     /**
      * Returns the value to which this map maps the specified key.  Returns
      * <tt>null</tt> if the map contains no mapping for this key.  A return
@@ -272,7 +275,7 @@ public class CompositeMap implements Map {
      *
      * @see #containsKey(Object)
      */
-    public Object get(Object key) {
+    public V get(Object key) {
         for (int i = this.composite.length - 1; i >= 0; --i) {
             if (this.composite[i].containsKey(key)) {
                 return this.composite[i].get(key);
@@ -280,7 +283,7 @@ public class CompositeMap implements Map {
         }
         return null;
     }
-    
+
     /**
      * Returns <tt>true</tt> if this map contains no key-value mappings.
      *
@@ -294,7 +297,7 @@ public class CompositeMap implements Map {
         }
         return true;
     }
-    
+
     /**
      * Returns a set view of the keys contained in this map.  The set is
      * backed by the map, so changes to the map are reflected in the set, and
@@ -310,14 +313,14 @@ public class CompositeMap implements Map {
      *
      * @return a set view of the keys contained in this map.
      */
-    public Set keySet() {
-        CompositeSet keys = new CompositeSet();
+    public Set<K> keySet() {
+        CompositeSet<K> keys = new CompositeSet<K>();
         for (int i = this.composite.length - 1; i >= 0; --i) {
             keys.addComposited(this.composite[i].keySet());
         }
         return keys;
     }
-    
+
     /**
      * Associates the specified value with the specified key in this map
      * (optional operation).  If the map previously contained a mapping for
@@ -343,13 +346,13 @@ public class CompositeMap implements Map {
      *            keys or values, and the specified key or value is
      *            <tt>null</tt>.
      */
-    public Object put(Object key, Object value) {
+    public V put(K key, V value) {
         if (this.mutator == null) {
             throw new UnsupportedOperationException("No mutator specified");
         }
         return this.mutator.put(this, this.composite, key, value);
     }
-    
+
     /**
      * Copies all of the mappings from the specified map to this map
      * (optional operation).  The effect of this call is equivalent to that
@@ -372,13 +375,13 @@ public class CompositeMap implements Map {
      *         this map does not permit <tt>null</tt> keys or values, and the
      *         specified map contains <tt>null</tt> keys or values.
      */
-    public void putAll(Map map) {
+    public void putAll(Map<? extends K, ? extends V> map) {
         if (this.mutator == null) {
             throw new UnsupportedOperationException("No mutator specified");
         }
         this.mutator.putAll(this, this.composite, map);
     }
-    
+
     /**
      * Removes the mapping for this key from this map if it is present
      * (optional operation).   More formally, if this map contains a mapping
@@ -404,7 +407,7 @@ public class CompositeMap implements Map {
      * @throws UnsupportedOperationException if the <tt>remove</tt> method is
      *         not supported by the composited map containing the key
      */
-    public Object remove(Object key) {
+    public V remove(Object key) {
         for (int i = this.composite.length - 1; i >= 0; --i) {
             if (this.composite[i].containsKey(key)) {
                 return this.composite[i].remove(key);
@@ -412,7 +415,7 @@ public class CompositeMap implements Map {
         }
         return null;
     }
-    
+
     /**
      * Returns the number of key-value mappings in this map.  If the
      * map contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
@@ -427,7 +430,7 @@ public class CompositeMap implements Map {
         }
         return size;
     }
-    
+
     /**
      * Returns a collection view of the values contained in this map.  The
      * collection is backed by the map, so changes to the map are reflected in
@@ -441,20 +444,21 @@ public class CompositeMap implements Map {
      *
      * @return a collection view of the values contained in this map.
      */
-    public Collection values() {
-        CompositeCollection keys = new CompositeCollection();
-        for (int i = this.composite.length - 1; i >= 0; --i) {
-            keys.addComposited(this.composite[i].values());
+    public Collection<V> values() {
+        CompositeCollection<V> values = new CompositeCollection<V>();
+        for (int i = composite.length - 1; i >= 0; --i) {
+            values.addComposited((Collection<V>) composite[i].values());
         }
-        return keys;
+        return values;
     }
-    
+
     /**
      * Checks if this Map equals another as per the Map specification.
-     * 
+     *
      * @param obj  the object to compare to
      * @return true if the maps are equal
      */
+    @SuppressWarnings("unchecked")
     public boolean equals(Object obj) {
         if (obj instanceof Map) {
             Map map = (Map) obj;
@@ -462,24 +466,24 @@ public class CompositeMap implements Map {
         }
         return false;
     }
-    
+
     /**
      * Gets a hash code for the Map as per the Map specification.
      */
     public int hashCode() {
         int code = 0;
-        for (Iterator i = this.entrySet().iterator(); i.hasNext();) {
-            code += i.next().hashCode();
+        for (Map.Entry<K, V> entry : entrySet()) {
+            code += entry.hashCode();
         }
         return code;
     }
-    
+
     /**
      * This interface allows definition for all of the indeterminate
      * mutators in a CompositeMap, as well as providing a hook for
      * callbacks on key collisions.
      */
-    public static interface MapMutator {
+    public static interface MapMutator<K, V> {
         /**
          * Called when adding a new Composited Map results in a
          * key collision.
@@ -490,9 +494,9 @@ public class CompositeMap implements Map {
          * @param added  the Map being added
          * @param intersect  the intersection of the keysets of the existing 
and added maps
          */
-        public void resolveCollision(
-            CompositeMap composite, Map existing, Map added, Collection 
intersect);
-        
+        public void resolveCollision(CompositeMap<K, V> composite, Map<K, V> 
existing,
+                Map<K, V> added, Collection<K> intersect);
+
         /**
          * Called when the CompositeMap.put() method is invoked.
          *
@@ -515,8 +519,8 @@ public class CompositeMap implements Map {
          *            keys or values, and the specified key or value is
          *            <tt>null</tt>.
          */
-        public Object put(CompositeMap map, Map[] composited, Object key, 
Object value);
-        
+        public V put(CompositeMap<K, V> map, Map<K, V>[] composited, K key, V 
value);
+
         /**
          * Called when the CompositeMap.putAll() method is invoked.
          *
@@ -533,6 +537,7 @@ public class CompositeMap implements Map {
          *            keys or values, and the specified key or value is
          *            <tt>null</tt>.
          */
-        public void putAll(CompositeMap map, Map[] composited, Map mapToAdd);
+        public void putAll(CompositeMap<K, V> map, Map<K, V>[] composited,
+                Map<? extends K, ? extends V> mapToAdd);
     }
 }

Reply via email to