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:16 UTC

[31/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/bidimap/AbstractBidiMapDecorator.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/commons/collections/bidimap/AbstractBidiMapDecorator.java b/src/java/org/apache/commons/collections/bidimap/AbstractBidiMapDecorator.java
index e725668..393cc4e 100644
--- a/src/java/org/apache/commons/collections/bidimap/AbstractBidiMapDecorator.java
+++ b/src/java/org/apache/commons/collections/bidimap/AbstractBidiMapDecorator.java
@@ -37,9 +37,8 @@ import org.apache.commons.collections.map.AbstractMapDecorator;
  * 
  * @author Stephen Colebourne
  */
-public abstract class AbstractBidiMapDecorator
-        extends AbstractMapDecorator
-        implements BidiMap {
+public abstract class AbstractBidiMapDecorator<K, V> extends AbstractMapDecorator<K, V> implements
+        BidiMap<K, V> {
 
     /**
      * Constructor that wraps (not copies).
@@ -47,7 +46,7 @@ public abstract class AbstractBidiMapDecorator
      * @param map  the map to decorate, must not be null
      * @throws IllegalArgumentException if the collection is null
      */
-    protected AbstractBidiMapDecorator(BidiMap map) {
+    protected AbstractBidiMapDecorator(BidiMap<K, V> map) {
         super(map);
     }
 
@@ -55,35 +54,25 @@ public abstract class AbstractBidiMapDecorator
      * Gets the map being decorated.
      * 
      * @return the decorated map
-     * @deprecated use decorated()
      */
-    protected BidiMap getBidiMap() {
-        return decorated();
-    }
-
-    /**
-     * Gets the map being decorated.
-     * 
-     * @return the decorated map
-     */
-    protected BidiMap decorated() {
-        return (BidiMap) super.decorated();
+    protected BidiMap<K, V> decorated() {
+        return (BidiMap<K, V>) super.decorated();
     }
 
     //-----------------------------------------------------------------------
-    public MapIterator mapIterator() {
+    public MapIterator<K, V> mapIterator() {
         return decorated().mapIterator();
     }
 
-    public Object getKey(Object value) {
+    public K getKey(Object value) {
         return decorated().getKey(value);
     }
 
-    public Object removeValue(Object value) {
+    public K removeValue(Object value) {
         return decorated().removeValue(value);
     }
 
-    public BidiMap inverseBidiMap() {
+    public BidiMap<V, K> inverseBidiMap() {
         return decorated().inverseBidiMap();
     }
 

http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/bidimap/AbstractDualBidiMap.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/commons/collections/bidimap/AbstractDualBidiMap.java b/src/java/org/apache/commons/collections/bidimap/AbstractDualBidiMap.java
index a07ffcb..b69049d 100644
--- a/src/java/org/apache/commons/collections/bidimap/AbstractDualBidiMap.java
+++ b/src/java/org/apache/commons/collections/bidimap/AbstractDualBidiMap.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.
@@ -33,38 +33,46 @@ import org.apache.commons.collections.keyvalue.AbstractMapEntryDecorator;
  * <p>
  * An implementation can be written simply by implementing the
  * <code>createMap</code> method.
- * 
+ *
  * @see DualHashBidiMap
  * @see DualTreeBidiMap
  * @since Commons Collections 3.0
  * @version $Id$
- * 
+ *
  * @author Matthew Hawthorne
  * @author Stephen Colebourne
  */
-public abstract class AbstractDualBidiMap implements BidiMap {
+public abstract class AbstractDualBidiMap<K, V> implements BidiMap<K, V> {
 
     /**
-     * Delegate map array.  The first map contains standard entries, and the 
-     * second contains inverses.
+     * Normal delegate map.
      */
-    protected transient final Map[] maps = new Map[2];
+    protected transient Map<K, V> normalMap;
+
+    /**
+     * Reverse delegate map.
+     */
+    protected transient Map<V, K> reverseMap;
+
     /**
      * Inverse view of this map.
      */
-    protected transient BidiMap inverseBidiMap = null;
+    protected transient BidiMap<V, K> inverseBidiMap = null;
+
     /**
      * View of the keys.
      */
-    protected transient Set keySet = null;
+    protected transient Set<K> keySet = null;
+
     /**
      * View of the values.
      */
-    protected transient Collection values = null;
+    protected transient Collection<V> values = null;
+
     /**
      * View of the entries.
      */
-    protected transient Set entrySet = null;
+    protected transient Set<Map.Entry<K, V>> entrySet = null;
 
     /**
      * Creates an empty map, initialised by <code>createMap</code>.
@@ -86,18 +94,18 @@ public abstract class AbstractDualBidiMap implements BidiMap {
      * Neither map is validated, so nulls may be passed in.
      * If you choose to do this then the subclass constructor must populate
      * the <code>maps[]</code> instance variable itself.
-     * 
+     *
      * @param normalMap  the normal direction map
      * @param reverseMap  the reverse direction map
      * @since Commons Collections 3.1
      */
-    protected AbstractDualBidiMap(Map normalMap, Map reverseMap) {
+    protected AbstractDualBidiMap(Map<K, V> normalMap, Map<V, K> reverseMap) {
         super();
-        maps[0] = normalMap;
-        maps[1] = reverseMap;
+        this.normalMap = normalMap;
+        this.reverseMap = reverseMap;
     }
 
-    /** 
+    /**
      * Constructs a map that decorates the specified maps,
      * used by the subclass <code>createBidiMap</code> implementation.
      *
@@ -105,90 +113,89 @@ public abstract class AbstractDualBidiMap implements BidiMap {
      * @param reverseMap  the reverse direction map
      * @param inverseBidiMap  the inverse BidiMap
      */
-    protected AbstractDualBidiMap(Map normalMap, Map reverseMap, BidiMap inverseBidiMap) {
+    protected AbstractDualBidiMap(Map<K, V> normalMap, Map<V, K> reverseMap, BidiMap<V, K> inverseBidiMap) {
         super();
-        maps[0] = normalMap;
-        maps[1] = reverseMap;
+        this.normalMap = normalMap;
+        this.reverseMap = reverseMap;
         this.inverseBidiMap = inverseBidiMap;
     }
 
     /**
      * Creates a new instance of the subclass.
-     * 
+     *
      * @param normalMap  the normal direction map
      * @param reverseMap  the reverse direction map
      * @param inverseMap  this map, which is the inverse in the new map
      * @return the inverse map
      */
-    protected abstract BidiMap createBidiMap(Map normalMap, Map reverseMap, BidiMap inverseMap);
+    protected abstract BidiMap<V, K> createBidiMap(Map<V, K> normalMap, Map<K, V> reverseMap, BidiMap<K, V> inverseMap);
 
     // Map delegation
     //-----------------------------------------------------------------------
-    public Object get(Object key) {
-        return maps[0].get(key);
+    public V get(Object key) {
+        return normalMap.get(key);
     }
 
     public int size() {
-        return maps[0].size();
+        return normalMap.size();
     }
 
     public boolean isEmpty() {
-        return maps[0].isEmpty();
+        return normalMap.isEmpty();
     }
 
     public boolean containsKey(Object key) {
-        return maps[0].containsKey(key);
+        return normalMap.containsKey(key);
     }
 
     public boolean equals(Object obj) {
-        return maps[0].equals(obj);
+        return normalMap.equals(obj);
     }
 
     public int hashCode() {
-        return maps[0].hashCode();
+        return normalMap.hashCode();
     }
 
     public String toString() {
-        return maps[0].toString();
+        return normalMap.toString();
     }
 
     // BidiMap changes
     //-----------------------------------------------------------------------
-    public Object put(Object key, Object value) {
-        if (maps[0].containsKey(key)) {
-            maps[1].remove(maps[0].get(key));
+    public V put(K key, V value) {
+        if (normalMap.containsKey(key)) {
+            reverseMap.remove(normalMap.get(key));
         }
-        if (maps[1].containsKey(value)) {
-            maps[0].remove(maps[1].get(value));
+        if (reverseMap.containsKey(value)) {
+            normalMap.remove(reverseMap.get(value));
         }
-        final Object obj = maps[0].put(key, value);
-        maps[1].put(value, key);
+        final V obj = normalMap.put(key, value);
+        reverseMap.put(value, key);
         return obj;
     }
-    
-    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 value = null;
-        if (maps[0].containsKey(key)) {
-            value = maps[0].remove(key);
-            maps[1].remove(value);
+    public V remove(Object key) {
+        V value = null;
+        if (normalMap.containsKey(key)) {
+            value = normalMap.remove(key);
+            reverseMap.remove(value);
         }
         return value;
     }
 
     public void clear() {
-        maps[0].clear();
-        maps[1].clear();
+        normalMap.clear();
+        reverseMap.clear();
     }
 
     public boolean containsValue(Object value) {
-        return maps[1].containsKey(value);
+        return reverseMap.containsKey(value);
     }
 
     // BidiMap
@@ -201,45 +208,45 @@ public abstract class AbstractDualBidiMap implements BidiMap {
      * The setValue() methods only allow a new value to be set.
      * If the value being set is already in the map, an IllegalArgumentException
      * is thrown (as setValue cannot change the size of the map).
-     * 
+     *
      * @return a map iterator
      */
-    public MapIterator mapIterator() {
-        return new BidiMapIterator(this);
+    public MapIterator<K, V> mapIterator() {
+        return new BidiMapIterator<K, V>(this);
     }
-    
-    public Object getKey(Object value) {
-        return maps[1].get(value);
+
+    public K getKey(Object value) {
+        return reverseMap.get(value);
     }
 
-    public Object removeValue(Object value) {
-        Object key = null;
-        if (maps[1].containsKey(value)) {
-            key = maps[1].remove(value);
-            maps[0].remove(key);
+    public K removeValue(Object value) {
+        K key = null;
+        if (reverseMap.containsKey(value)) {
+            key = reverseMap.remove(value);
+            normalMap.remove(key);
         }
         return key;
     }
 
-    public BidiMap inverseBidiMap() {
+    public BidiMap<V, K> inverseBidiMap() {
         if (inverseBidiMap == null) {
-            inverseBidiMap = createBidiMap(maps[1], maps[0], this);
+            inverseBidiMap = createBidiMap(reverseMap, normalMap, this);
         }
         return inverseBidiMap;
     }
-    
+
     // Map views
     //-----------------------------------------------------------------------
     /**
      * Gets a keySet view of the map.
      * Changes made on the view are reflected in the map.
      * The set supports remove and clear but not add.
-     * 
+     *
      * @return the keySet view
      */
-    public Set keySet() {
+    public Set<K> keySet() {
         if (keySet == null) {
-            keySet = new KeySet(this);
+            keySet = new KeySet<K>(this);
         }
         return keySet;
     }
@@ -247,24 +254,24 @@ public abstract class AbstractDualBidiMap implements BidiMap {
     /**
      * Creates a key set iterator.
      * Subclasses can override this to return iterators with different properties.
-     * 
+     *
      * @param iterator  the iterator to decorate
      * @return the keySet iterator
      */
-    protected Iterator createKeySetIterator(Iterator iterator) {
-        return new KeySetIterator(iterator, this);
+    protected Iterator<K> createKeySetIterator(Iterator<K> iterator) {
+        return new KeySetIterator<K>(iterator, this);
     }
 
     /**
      * Gets a values view of the map.
      * Changes made on the view are reflected in the map.
      * The set supports remove and clear but not add.
-     * 
+     *
      * @return the values view
      */
-    public Collection values() {
+    public Collection<V> values() {
         if (values == null) {
-            values = new Values(this);
+            values = new Values<V>(this);
         }
         return values;
     }
@@ -272,12 +279,12 @@ public abstract class AbstractDualBidiMap implements BidiMap {
     /**
      * Creates a values iterator.
      * Subclasses can override this to return iterators with different properties.
-     * 
+     *
      * @param iterator  the iterator to decorate
      * @return the values iterator
      */
-    protected Iterator createValuesIterator(Iterator iterator) {
-        return new ValuesIterator(iterator, this);
+    protected Iterator<V> createValuesIterator(Iterator<V> iterator) {
+        return new ValuesIterator<V>(iterator, this);
     }
 
     /**
@@ -288,53 +295,54 @@ public abstract class AbstractDualBidiMap implements BidiMap {
      * The Map Entry setValue() method only allow a new value to be set.
      * If the value being set is already in the map, an IllegalArgumentException
      * is thrown (as setValue cannot change the size of the map).
-     * 
+     *
      * @return the entrySet view
      */
-    public Set entrySet() {
+    public Set<Map.Entry<K, V>> entrySet() {
         if (entrySet == null) {
-            entrySet = new EntrySet(this);
+            entrySet = new EntrySet<K, V>(this);
         }
         return entrySet;
     }
-    
+
     /**
      * Creates an entry set iterator.
      * Subclasses can override this to return iterators with different properties.
-     * 
+     *
      * @param iterator  the iterator to decorate
      * @return the entrySet iterator
      */
-    protected Iterator createEntrySetIterator(Iterator iterator) {
-        return new EntrySetIterator(iterator, this);
+    protected Iterator<Map.Entry<K, V>> createEntrySetIterator(Iterator<Map.Entry<K, V>> iterator) {
+        return new EntrySetIterator<K, V>(iterator, this);
     }
 
     //-----------------------------------------------------------------------
     /**
      * Inner class View.
      */
-    protected static abstract class View extends AbstractCollectionDecorator {
-        
+    @SuppressWarnings("serial")
+    protected static abstract class View<K, V, E> extends AbstractCollectionDecorator<E> {
+
         /** The parent map */
-        protected final AbstractDualBidiMap parent;
-        
+        protected final AbstractDualBidiMap<K, V> parent;
+
         /**
          * Constructs a new view of the BidiMap.
-         * 
+         *
          * @param coll  the collection view being decorated
          * @param parent  the parent BidiMap
          */
-        protected View(Collection coll, AbstractDualBidiMap parent) {
+        protected View(Collection<E> coll, AbstractDualBidiMap<K, V> parent) {
             super(coll);
             this.parent = parent;
         }
 
-        public boolean removeAll(Collection coll) {
+        public boolean removeAll(Collection<?> coll) {
             if (parent.isEmpty() || coll.isEmpty()) {
                 return false;
             }
             boolean modified = false;
-            Iterator it = iterator();
+            Iterator<E> it = iterator();
             while (it.hasNext()) {
                 if (coll.contains(it.next())) {
                     it.remove();
@@ -344,7 +352,7 @@ public abstract class AbstractDualBidiMap implements BidiMap {
             return modified;
         }
 
-        public boolean retainAll(Collection coll) {
+        public boolean retainAll(Collection<?> coll) {
             if (parent.isEmpty()) {
                 return false;
             }
@@ -353,7 +361,7 @@ public abstract class AbstractDualBidiMap implements BidiMap {
                 return true;
             }
             boolean modified = false;
-            Iterator it = iterator();
+            Iterator<E> it = iterator();
             while (it.hasNext()) {
                 if (coll.contains(it.next()) == false) {
                     it.remove();
@@ -362,80 +370,86 @@ public abstract class AbstractDualBidiMap implements BidiMap {
             }
             return modified;
         }
-        
+
         public void clear() {
             parent.clear();
         }
     }
-    
+
     //-----------------------------------------------------------------------
     /**
      * Inner class KeySet.
      */
-    protected static class KeySet extends View implements Set {
-        
+    protected static class KeySet<K> extends View<K, Object, K> implements Set<K> {
+
+        /** Serialization version */
+        private static final long serialVersionUID = -7107935777385040694L;
+
         /**
          * Constructs a new view of the BidiMap.
-         * 
+         *
          * @param parent  the parent BidiMap
          */
-        protected KeySet(AbstractDualBidiMap parent) {
-            super(parent.maps[0].keySet(), parent);
+        @SuppressWarnings("unchecked")
+        protected KeySet(AbstractDualBidiMap<K, ?> parent) {
+            super(parent.normalMap.keySet(), (AbstractDualBidiMap<K, Object>) parent);
         }
 
-        public Iterator iterator() {
+        public Iterator<K> iterator() {
             return parent.createKeySetIterator(super.iterator());
         }
-        
+
         public boolean contains(Object key) {
-            return parent.maps[0].containsKey(key);
+            return parent.normalMap.containsKey(key);
         }
 
         public boolean remove(Object key) {
-            if (parent.maps[0].containsKey(key)) {
-                Object value = parent.maps[0].remove(key);
-                parent.maps[1].remove(value);
+            if (parent.normalMap.containsKey(key)) {
+                Object value = parent.normalMap.remove(key);
+                parent.reverseMap.remove(value);
                 return true;
             }
             return false;
         }
     }
-    
+
     /**
      * Inner class KeySetIterator.
      */
-    protected static class KeySetIterator extends AbstractIteratorDecorator {
-        
+    protected static class KeySetIterator<K> extends AbstractIteratorDecorator<K> {
+
         /** The parent map */
-        protected final AbstractDualBidiMap parent;
+        protected final AbstractDualBidiMap<K, ?> parent;
+
         /** The last returned key */
-        protected Object lastKey = null;
+        protected K lastKey = null;
+
         /** Whether remove is allowed at present */
         protected boolean canRemove = false;
-        
+
         /**
          * Constructor.
          * @param iterator  the iterator to decorate
          * @param parent  the parent map
          */
-        protected KeySetIterator(Iterator iterator, AbstractDualBidiMap parent) {
+        protected KeySetIterator(Iterator<K> iterator, AbstractDualBidiMap<K, ?> parent) {
             super(iterator);
             this.parent = parent;
         }
-        
-        public Object next() {
+
+        public K next() {
             lastKey = super.next();
             canRemove = true;
             return lastKey;
         }
-        
+
         public void remove() {
             if (canRemove == false) {
                 throw new IllegalStateException("Iterator remove() can only be called once after next()");
             }
-            Object value = parent.maps[0].get(lastKey);
+            Object value = parent.normalMap.get(lastKey);
             super.remove();
-            parent.maps[1].remove(value);
+            parent.reverseMap.remove(value);
             lastKey = null;
             canRemove = false;
         }
@@ -445,69 +459,76 @@ public abstract class AbstractDualBidiMap implements BidiMap {
     /**
      * Inner class Values.
      */
-    protected static class Values extends View implements Set {
-        
+    protected static class Values<V> extends View<Object, V, V> implements Set<V> {
+
+        /** Serialization version */
+        private static final long serialVersionUID = 4023777119829639864L;
+
         /**
          * Constructs a new view of the BidiMap.
-         * 
+         *
          * @param parent  the parent BidiMap
          */
-        protected Values(AbstractDualBidiMap parent) {
-            super(parent.maps[0].values(), parent);
+        @SuppressWarnings("unchecked")
+        protected Values(AbstractDualBidiMap<?, V> parent) {
+            super(parent.normalMap.values(), (AbstractDualBidiMap<Object, V>) parent);
         }
 
-        public Iterator iterator() {
+        public Iterator<V> iterator() {
             return parent.createValuesIterator(super.iterator());
         }
-        
+
         public boolean contains(Object value) {
-            return parent.maps[1].containsKey(value);
+            return parent.reverseMap.containsKey(value);
         }
 
         public boolean remove(Object value) {
-            if (parent.maps[1].containsKey(value)) {
-                Object key = parent.maps[1].remove(value);
-                parent.maps[0].remove(key);
+            if (parent.reverseMap.containsKey(value)) {
+                Object key = parent.reverseMap.remove(value);
+                parent.normalMap.remove(key);
                 return true;
             }
             return false;
         }
     }
-    
+
     /**
      * Inner class ValuesIterator.
      */
-    protected static class ValuesIterator extends AbstractIteratorDecorator {
-        
+    protected static class ValuesIterator<V> extends AbstractIteratorDecorator<V> {
+
         /** The parent map */
-        protected final AbstractDualBidiMap parent;
+        protected final AbstractDualBidiMap<Object, V> parent;
+
         /** The last returned value */
-        protected Object lastValue = null;
+        protected V lastValue = null;
+
         /** Whether remove is allowed at present */
         protected boolean canRemove = false;
-        
+
         /**
          * Constructor.
          * @param iterator  the iterator to decorate
          * @param parent  the parent map
          */
-        protected ValuesIterator(Iterator iterator, AbstractDualBidiMap parent) {
+        @SuppressWarnings("unchecked")
+        protected ValuesIterator(Iterator<V> iterator, AbstractDualBidiMap<?, V> parent) {
             super(iterator);
-            this.parent = parent;
+            this.parent = (AbstractDualBidiMap<Object, V>) parent;
         }
-        
-        public Object next() {
+
+        public V next() {
             lastValue = super.next();
             canRemove = true;
             return lastValue;
         }
-        
+
         public void remove() {
             if (canRemove == false) {
                 throw new IllegalStateException("Iterator remove() can only be called once after next()");
             }
             super.remove(); // removes from maps[0]
-            parent.maps[1].remove(lastValue);
+            parent.reverseMap.remove(lastValue);
             lastValue = null;
             canRemove = false;
         }
@@ -517,67 +538,72 @@ public abstract class AbstractDualBidiMap implements BidiMap {
     /**
      * Inner class EntrySet.
      */
-    protected static class EntrySet extends View implements Set {
-        
+    protected static class EntrySet<K, V> extends View<K, V, Map.Entry<K, V>> implements Set<Map.Entry<K, V>> {
+
+        /** Serialization version */
+        private static final long serialVersionUID = 4040410962603292348L;
+
         /**
          * Constructs a new view of the BidiMap.
-         * 
+         *
          * @param parent  the parent BidiMap
          */
-        protected EntrySet(AbstractDualBidiMap parent) {
-            super(parent.maps[0].entrySet(), parent);
+        protected EntrySet(AbstractDualBidiMap<K, V> parent) {
+            super(parent.normalMap.entrySet(), parent);
         }
 
-        public Iterator iterator() {
+        public Iterator<Map.Entry<K, V>> iterator() {
             return parent.createEntrySetIterator(super.iterator());
         }
-        
+
         public boolean remove(Object obj) {
             if (obj instanceof Map.Entry == false) {
                 return false;
             }
-            Map.Entry entry = (Map.Entry) obj;
+            Map.Entry<?, ?> entry = (Map.Entry<?, ?>) obj;
             Object key = entry.getKey();
             if (parent.containsKey(key)) {
-                Object value = parent.maps[0].get(key);
+                V value = parent.normalMap.get(key);
                 if (value == null ? entry.getValue() == null : value.equals(entry.getValue())) {
-                    parent.maps[0].remove(key);
-                    parent.maps[1].remove(value);
+                    parent.normalMap.remove(key);
+                    parent.reverseMap.remove(value);
                     return true;
                 }
             }
             return false;
         }
     }
-    
+
     /**
      * Inner class EntrySetIterator.
      */
-    protected static class EntrySetIterator extends AbstractIteratorDecorator {
-        
+    protected static class EntrySetIterator<K, V> extends AbstractIteratorDecorator<Map.Entry<K, V>> {
+
         /** The parent map */
-        protected final AbstractDualBidiMap parent;
+        protected final AbstractDualBidiMap<K, V> parent;
+
         /** The last returned entry */
-        protected Map.Entry last = null;
+        protected Map.Entry<K, V> last = null;
+
         /** Whether remove is allowed at present */
         protected boolean canRemove = false;
-        
+
         /**
          * Constructor.
          * @param iterator  the iterator to decorate
          * @param parent  the parent map
          */
-        protected EntrySetIterator(Iterator iterator, AbstractDualBidiMap parent) {
+        protected EntrySetIterator(Iterator<Map.Entry<K, V>> iterator, AbstractDualBidiMap<K, V> parent) {
             super(iterator);
             this.parent = parent;
         }
-        
-        public Object next() {
-            last = new MapEntry((Map.Entry) super.next(), parent);
+
+        public Map.Entry<K, V> next() {
+            last = new MapEntry<K, V>(super.next(), parent);
             canRemove = true;
             return last;
         }
-        
+
         public void remove() {
             if (canRemove == false) {
                 throw new IllegalStateException("Iterator remove() can only be called once after next()");
@@ -585,7 +611,7 @@ public abstract class AbstractDualBidiMap implements BidiMap {
             // store value as remove may change the entry in the decorator (eg.TreeMap)
             Object value = last.getValue();
             super.remove();
-            parent.maps[1].remove(value);
+            parent.reverseMap.remove(value);
             last = null;
             canRemove = false;
         }
@@ -594,117 +620,119 @@ public abstract class AbstractDualBidiMap implements BidiMap {
     /**
      * Inner class MapEntry.
      */
-    protected static class MapEntry extends AbstractMapEntryDecorator {
+    protected static class MapEntry<K, V> extends AbstractMapEntryDecorator<K, V> {
+
+        /** The parent map */
+        protected final AbstractDualBidiMap<K, V> parent;
 
-        /** The parent map */        
-        protected final AbstractDualBidiMap parent;
-        
         /**
          * Constructor.
          * @param entry  the entry to decorate
          * @param parent  the parent map
          */
-        protected MapEntry(Map.Entry entry, AbstractDualBidiMap parent) {
+        protected MapEntry(Map.Entry<K, V> entry, AbstractDualBidiMap<K, V> parent) {
             super(entry);
             this.parent = parent;
         }
-        
-        public Object setValue(Object value) {
-            Object key = MapEntry.this.getKey();
-            if (parent.maps[1].containsKey(value) &&
-                parent.maps[1].get(value) != key) {
+
+        public V setValue(V value) {
+            K key = MapEntry.this.getKey();
+            if (parent.reverseMap.containsKey(value) &&
+                parent.reverseMap.get(value) != key) {
                 throw new IllegalArgumentException("Cannot use setValue() when the object being set is already in the map");
             }
             parent.put(key, value);
-            final Object oldValue = super.setValue(value);
+            final V oldValue = super.setValue(value);
             return oldValue;
         }
     }
-    
+
     /**
      * Inner class MapIterator.
      */
-    protected static class BidiMapIterator implements MapIterator, ResettableIterator {
-        
+    protected static class BidiMapIterator<K, V> implements MapIterator<K, V>, ResettableIterator<K> {
+
         /** The parent map */
-        protected final AbstractDualBidiMap parent;
+        protected final AbstractDualBidiMap<K, V> parent;
+
         /** The iterator being wrapped */
-        protected Iterator iterator;
+        protected Iterator<Map.Entry<K, V>> iterator;
+
         /** The last returned entry */
-        protected Map.Entry last = null;
+        protected Map.Entry<K, V> last = null;
+
         /** Whether remove is allowed at present */
         protected boolean canRemove = false;
-        
+
         /**
          * Constructor.
          * @param parent  the parent map
          */
-        protected BidiMapIterator(AbstractDualBidiMap parent) {
+        protected BidiMapIterator(AbstractDualBidiMap<K, V> parent) {
             super();
             this.parent = parent;
-            this.iterator = parent.maps[0].entrySet().iterator();
+            this.iterator = parent.normalMap.entrySet().iterator();
         }
-        
+
         public boolean hasNext() {
             return iterator.hasNext();
         }
-        
-        public Object next() {
-            last = (Map.Entry) iterator.next();
+
+        public K next() {
+            last = iterator.next();
             canRemove = true;
             return last.getKey();
         }
-        
+
         public void remove() {
             if (canRemove == false) {
                 throw new IllegalStateException("Iterator remove() can only be called once after next()");
             }
             // store value as remove may change the entry in the decorator (eg.TreeMap)
-            Object value = last.getValue();
+            V value = last.getValue();
             iterator.remove();
-            parent.maps[1].remove(value);
+            parent.reverseMap.remove(value);
             last = null;
             canRemove = false;
         }
-        
-        public Object getKey() {
+
+        public K getKey() {
             if (last == null) {
                 throw new IllegalStateException("Iterator getKey() can only be called after next() and before remove()");
             }
             return last.getKey();
         }
 
-        public Object getValue() {
+        public V getValue() {
             if (last == null) {
                 throw new IllegalStateException("Iterator getValue() can only be called after next() and before remove()");
             }
             return last.getValue();
         }
-        
-        public Object setValue(Object value) {
+
+        public V setValue(V value) {
             if (last == null) {
                 throw new IllegalStateException("Iterator setValue() can only be called after next() and before remove()");
             }
-            if (parent.maps[1].containsKey(value) &&
-                parent.maps[1].get(value) != last.getKey()) {
+            if (parent.reverseMap.containsKey(value) &&
+                parent.reverseMap.get(value) != last.getKey()) {
                 throw new IllegalArgumentException("Cannot use setValue() when the object being set is already in the map");
             }
             return parent.put(last.getKey(), value);
         }
-        
+
         public void reset() {
-            iterator = parent.maps[0].entrySet().iterator();
+            iterator = parent.normalMap.entrySet().iterator();
             last = null;
             canRemove = false;
         }
-        
+
         public String toString() {
             if (last != null) {
                 return "MapIterator[" + getKey() + "=" + getValue() + "]";
-            } else {
-                return "MapIterator[]";
             }
+            return "MapIterator[]";
         }
     }
-    
+
 }

http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/bidimap/AbstractOrderedBidiMapDecorator.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/commons/collections/bidimap/AbstractOrderedBidiMapDecorator.java b/src/java/org/apache/commons/collections/bidimap/AbstractOrderedBidiMapDecorator.java
index 7a96af6..1602ef8 100644
--- a/src/java/org/apache/commons/collections/bidimap/AbstractOrderedBidiMapDecorator.java
+++ b/src/java/org/apache/commons/collections/bidimap/AbstractOrderedBidiMapDecorator.java
@@ -36,9 +36,9 @@ import org.apache.commons.collections.OrderedMapIterator;
  * 
  * @author Stephen Colebourne
  */
-public abstract class AbstractOrderedBidiMapDecorator
-        extends AbstractBidiMapDecorator
-        implements OrderedBidiMap {
+public abstract class AbstractOrderedBidiMapDecorator<K, V>
+        extends AbstractBidiMapDecorator<K, V>
+        implements OrderedBidiMap<K, V> {
 
     /**
      * Constructor that wraps (not copies).
@@ -46,7 +46,7 @@ public abstract class AbstractOrderedBidiMapDecorator
      * @param map  the map to decorate, must not be null
      * @throws IllegalArgumentException if the collection is null
      */
-    protected AbstractOrderedBidiMapDecorator(OrderedBidiMap map) {
+    protected AbstractOrderedBidiMapDecorator(OrderedBidiMap<K, V> map) {
         super(map);
     }
 
@@ -54,44 +54,35 @@ public abstract class AbstractOrderedBidiMapDecorator
      * Gets the map being decorated.
      * 
      * @return the decorated map
-     * @deprecated use decorated()
      */
-    protected OrderedBidiMap getOrderedBidiMap() {
-        return decorated();
-    }
-
-    /**
-     * Gets the map being decorated.
-     * 
-     * @return the decorated map
-     */
-    protected OrderedBidiMap decorated() {
-        return (OrderedBidiMap) super.decorated();
+    protected OrderedBidiMap<K, V> decorated() {
+        return (OrderedBidiMap<K, V>) super.decorated();
     }
 
     //-----------------------------------------------------------------------
-    public OrderedMapIterator orderedMapIterator() {
-        return decorated().orderedMapIterator();
+    public OrderedMapIterator<K, V> mapIterator() {
+        return decorated().mapIterator();
     }
 
-    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 OrderedBidiMap inverseOrderedBidiMap() {
-        return decorated().inverseOrderedBidiMap();
+    @Override
+    public OrderedBidiMap<V, K> inverseBidiMap() {
+        return decorated().inverseBidiMap();
     }
 
 }

http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/bidimap/AbstractSortedBidiMapDecorator.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/commons/collections/bidimap/AbstractSortedBidiMapDecorator.java b/src/java/org/apache/commons/collections/bidimap/AbstractSortedBidiMapDecorator.java
index af56d2d..3fec108 100644
--- a/src/java/org/apache/commons/collections/bidimap/AbstractSortedBidiMapDecorator.java
+++ b/src/java/org/apache/commons/collections/bidimap/AbstractSortedBidiMapDecorator.java
@@ -38,9 +38,8 @@ import org.apache.commons.collections.SortedBidiMap;
  * 
  * @author Stephen Colebourne
  */
-public abstract class AbstractSortedBidiMapDecorator
-        extends AbstractOrderedBidiMapDecorator
-        implements SortedBidiMap {
+public abstract class AbstractSortedBidiMapDecorator<K, V> extends
+        AbstractOrderedBidiMapDecorator<K, V> implements SortedBidiMap<K, V> {
 
     /**
      * Constructor that wraps (not copies).
@@ -48,7 +47,7 @@ public abstract class AbstractSortedBidiMapDecorator
      * @param map  the map to decorate, must not be null
      * @throws IllegalArgumentException if the collection is null
      */
-    public AbstractSortedBidiMapDecorator(SortedBidiMap map) {
+    public AbstractSortedBidiMapDecorator(SortedBidiMap<K, V> map) {
         super(map);
     }
 
@@ -56,39 +55,34 @@ public abstract class AbstractSortedBidiMapDecorator
      * Gets the map being decorated.
      * 
      * @return the decorated map
-     * @deprecated use decorated()
      */
-    protected SortedBidiMap getSortedBidiMap() {
-        return decorated();
-    }
-
-    /**
-     * Gets the map being decorated.
-     * 
-     * @return the decorated map
-     */
-    protected SortedBidiMap decorated() {
-        return (SortedBidiMap) super.decorated();
+    protected SortedBidiMap<K, V> decorated() {
+        return (SortedBidiMap<K, V>) super.decorated();
     }
 
     //-----------------------------------------------------------------------
-    public SortedBidiMap inverseSortedBidiMap() {
-        return getSortedBidiMap().inverseSortedBidiMap();
+    @Override
+    public SortedBidiMap<V, K> inverseBidiMap() {
+        return decorated().inverseBidiMap();
     }
 
-    public Comparator comparator() {
+    public Comparator<? super K> comparator() {
         return decorated().comparator();
     }
 
-    public SortedMap subMap(Object fromKey, Object toKey) {
+    public Comparator<? super V> valueComparator() {
+        return decorated().valueComparator();
+    }
+
+    public SortedMap<K, V> subMap(K fromKey, K toKey) {
         return decorated().subMap(fromKey, toKey);
     }
 
-    public SortedMap headMap(Object toKey) {
+    public SortedMap<K, V> headMap(K toKey) {
         return decorated().headMap(toKey);
     }
 
-    public SortedMap tailMap(Object fromKey) {
+    public SortedMap<K, V> tailMap(K fromKey) {
         return decorated().tailMap(fromKey);
     }
 

http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/bidimap/DualHashBidiMap.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/commons/collections/bidimap/DualHashBidiMap.java b/src/java/org/apache/commons/collections/bidimap/DualHashBidiMap.java
index 067b2a6..b0927aa 100644
--- a/src/java/org/apache/commons/collections/bidimap/DualHashBidiMap.java
+++ b/src/java/org/apache/commons/collections/bidimap/DualHashBidiMap.java
@@ -42,8 +42,7 @@ import org.apache.commons.collections.BidiMap;
  * @author Matthew Hawthorne
  * @author Stephen Colebourne
  */
-public class DualHashBidiMap
-        extends AbstractDualBidiMap implements Serializable {
+public class DualHashBidiMap<K, V> extends AbstractDualBidiMap<K, V> implements Serializable {
 
     /** Ensure serialization compatibility */
     private static final long serialVersionUID = 721969328361808L;
@@ -52,7 +51,7 @@ public class DualHashBidiMap
      * Creates an empty <code>HashBidiMap</code>.
      */
     public DualHashBidiMap() {
-        super(new HashMap(), new HashMap());
+        super(new HashMap<K, V>(), new HashMap<V, K>());
     }
 
     /** 
@@ -61,8 +60,8 @@ public class DualHashBidiMap
      *
      * @param map  the map whose mappings are to be placed in this map
      */
-    public DualHashBidiMap(Map map) {
-        super(new HashMap(), new HashMap());
+    public DualHashBidiMap(Map<K, V> map) {
+        super(new HashMap<K, V>(), new HashMap<V, K>());
         putAll(map);
     }
     
@@ -73,7 +72,7 @@ public class DualHashBidiMap
      * @param reverseMap  the reverse direction map
      * @param inverseBidiMap  the inverse BidiMap
      */
-    protected DualHashBidiMap(Map normalMap, Map reverseMap, BidiMap inverseBidiMap) {
+    protected DualHashBidiMap(Map<K, V> normalMap, Map<V, K> reverseMap, BidiMap<V, K> inverseBidiMap) {
         super(normalMap, reverseMap, inverseBidiMap);
     }
 
@@ -85,21 +84,22 @@ public class DualHashBidiMap
      * @param inverseBidiMap  the inverse BidiMap
      * @return new bidi map
      */
-    protected BidiMap createBidiMap(Map normalMap, Map reverseMap, BidiMap inverseBidiMap) {
-        return new DualHashBidiMap(normalMap, reverseMap, inverseBidiMap);
+    protected BidiMap<V, K> createBidiMap(Map<V, K> normalMap, Map<K, V> reverseMap, BidiMap<K, V> inverseBidiMap) {
+        return new DualHashBidiMap<V, K>(normalMap, reverseMap, inverseBidiMap);
     }
 
     // Serialization
     //-----------------------------------------------------------------------
     private void writeObject(ObjectOutputStream out) throws IOException {
         out.defaultWriteObject();
-        out.writeObject(maps[0]);
+        out.writeObject(normalMap);
     }
 
+    @SuppressWarnings("unchecked")
     private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
         in.defaultReadObject();
-        maps[0] = new HashMap();
-        maps[1] = new HashMap();
+        normalMap = new HashMap();
+        reverseMap = new HashMap();
         Map map = (Map) in.readObject();
         putAll(map);
     }

http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/bidimap/DualTreeBidiMap.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/commons/collections/bidimap/DualTreeBidiMap.java b/src/java/org/apache/commons/collections/bidimap/DualTreeBidiMap.java
index fb8aef0..5ced759 100644
--- a/src/java/org/apache/commons/collections/bidimap/DualTreeBidiMap.java
+++ b/src/java/org/apache/commons/collections/bidimap/DualTreeBidiMap.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.
@@ -48,97 +48,110 @@ import org.apache.commons.collections.map.AbstractSortedMapDecorator;
  * <p>
  * NOTE: From Commons Collections 3.1, all subclasses will use <code>TreeMap</code>
  * and the flawed <code>createMap</code> method is ignored.
- * 
+ *
  * @since Commons Collections 3.0
  * @version $Id$
- * 
+ *
  * @author Matthew Hawthorne
  * @author Stephen Colebourne
  */
-public class DualTreeBidiMap
-        extends AbstractDualBidiMap implements SortedBidiMap, Serializable {
+public class DualTreeBidiMap<K, V> extends AbstractDualBidiMap<K, V> implements
+        SortedBidiMap<K, V>, Serializable {
 
     /** Ensure serialization compatibility */
     private static final long serialVersionUID = 721969328361809L;
-    /** The comparator to use */
-    protected final Comparator comparator;
+
+    /** The key comparator to use */
+    protected final Comparator<? super K> comparator;
+
+    /** The value comparator to use */
+    protected final Comparator<? super V> valueComparator;
     
     /**
      * Creates an empty <code>DualTreeBidiMap</code>
      */
     public DualTreeBidiMap() {
-        super(new TreeMap(), new TreeMap());
+        super(new TreeMap<K, V>(), new TreeMap<V, K>());
         this.comparator = null;
+        this.valueComparator = null;
     }
 
-    /** 
+    /**
      * Constructs a <code>DualTreeBidiMap</code> and copies the mappings from
-     * specified <code>Map</code>.  
+     * specified <code>Map</code>.
      *
      * @param map  the map whose mappings are to be placed in this map
      */
-    public DualTreeBidiMap(Map map) {
-        super(new TreeMap(), new TreeMap());
+    public DualTreeBidiMap(Map<K, V> map) {
+        super(new TreeMap<K, V>(), new TreeMap<V, K>());
         putAll(map);
         this.comparator = null;
+        this.valueComparator = null;
     }
 
-    /** 
+    /**
      * Constructs a <code>DualTreeBidiMap</code> using the specified Comparator.
      *
-     * @param comparator  the Comparator
+     * @param keyComparator  the Comparator
      */
-    public DualTreeBidiMap(Comparator comparator) {
-        super(new TreeMap(comparator), new TreeMap(comparator));
-        this.comparator = comparator;
+    public DualTreeBidiMap(Comparator<? super K> keyComparator, Comparator<? super V> valueComparator) {
+        super(new TreeMap<K, V>(keyComparator), new TreeMap<V, K>(valueComparator));
+        this.comparator = keyComparator;
+        this.valueComparator = valueComparator;
     }
 
-    /** 
+    /**
      * Constructs a <code>DualTreeBidiMap</code> that decorates the specified maps.
      *
      * @param normalMap  the normal direction map
      * @param reverseMap  the reverse direction map
      * @param inverseBidiMap  the inverse BidiMap
      */
-    protected DualTreeBidiMap(Map normalMap, Map reverseMap, BidiMap inverseBidiMap) {
+    protected DualTreeBidiMap(Map<K, V> normalMap, Map<V, K> reverseMap, BidiMap<V, K> inverseBidiMap) {
         super(normalMap, reverseMap, inverseBidiMap);
-        this.comparator = ((SortedMap) normalMap).comparator();
+        this.comparator = ((SortedMap<K, V>) normalMap).comparator();
+        this.valueComparator = ((SortedMap<V, K>) reverseMap).comparator();
     }
 
     /**
      * Creates a new instance of this object.
-     * 
+     *
      * @param normalMap  the normal direction map
      * @param reverseMap  the reverse direction map
      * @param inverseMap  the inverse BidiMap
      * @return new bidi map
      */
-    protected BidiMap createBidiMap(Map normalMap, Map reverseMap, BidiMap inverseMap) {
-        return new DualTreeBidiMap(normalMap, reverseMap, inverseMap);
+    protected DualTreeBidiMap<V, K> createBidiMap(Map<V, K> normalMap, Map<K, V> reverseMap, BidiMap<K, V> inverseMap) {
+        return new DualTreeBidiMap<V, K>(normalMap, reverseMap, inverseMap);
     }
 
     //-----------------------------------------------------------------------
-    public Comparator comparator() {
-        return ((SortedMap) maps[0]).comparator();
+    public Comparator<? super K> comparator() {
+        return ((SortedMap<K, V>) normalMap).comparator();
     }
 
-    public Object firstKey() {
-        return ((SortedMap) maps[0]).firstKey();
+    public Comparator<? super V> valueComparator() {
+        return ((SortedMap<V, K>) reverseMap).comparator();
+        
     }
 
-    public Object lastKey() {
-        return ((SortedMap) maps[0]).lastKey();
+    public K firstKey() {
+        return ((SortedMap<K, V>) normalMap).firstKey();
     }
 
-    public Object nextKey(Object key) {
+    public K lastKey() {
+        return ((SortedMap<K, V>) normalMap).lastKey();
+    }
+
+    public K nextKey(K key) {
         if (isEmpty()) {
             return null;
         }
-        if (maps[0] instanceof OrderedMap) {
-            return ((OrderedMap) maps[0]).nextKey(key);
+        if (normalMap instanceof OrderedMap) {
+            return ((OrderedMap<K, ?>) normalMap).nextKey(key);
         }
-        SortedMap sm = (SortedMap) maps[0];
-        Iterator it = sm.tailMap(key).keySet().iterator();
+        SortedMap<K, V> sm = (SortedMap<K, V>) normalMap;
+        Iterator<K> it = sm.tailMap(key).keySet().iterator();
         it.next();
         if (it.hasNext()) {
             return it.next();
@@ -146,15 +159,15 @@ public class DualTreeBidiMap
         return null;
     }
 
-    public Object previousKey(Object key) {
+    public K previousKey(K key) {
         if (isEmpty()) {
             return null;
         }
-        if (maps[0] instanceof OrderedMap) {
-            return ((OrderedMap) maps[0]).previousKey(key);
+        if (normalMap instanceof OrderedMap) {
+            return ((OrderedMap<K, V>) normalMap).previousKey(key);
         }
-        SortedMap sm = (SortedMap) maps[0];
-        SortedMap hm = sm.headMap(key);
+        SortedMap<K, V> sm = (SortedMap<K, V>) normalMap;
+        SortedMap<K, V> hm = sm.headMap(key);
         if (hm.isEmpty()) {
             return null;
         }
@@ -167,81 +180,94 @@ public class DualTreeBidiMap
      * <p>
      * This implementation copies the elements to an ArrayList in order to
      * provide the forward/backward behaviour.
-     * 
+     *
      * @return a new ordered map iterator
      */
-    public OrderedMapIterator orderedMapIterator() {
-        return new BidiOrderedMapIterator(this);
+    public OrderedMapIterator<K, V> mapIterator() {
+        return new BidiOrderedMapIterator<K, V>(this);
     }
 
-    public SortedBidiMap inverseSortedBidiMap() {
-        return (SortedBidiMap) inverseBidiMap();
+    public SortedBidiMap<V, K> inverseSortedBidiMap() {
+        return (SortedBidiMap<V, K>) inverseBidiMap();
     }
 
-    public OrderedBidiMap inverseOrderedBidiMap() {
-        return (OrderedBidiMap) inverseBidiMap();
+    public OrderedBidiMap<V, K> inverseOrderedBidiMap() {
+        return (OrderedBidiMap<V, K>) inverseBidiMap();
     }
 
     //-----------------------------------------------------------------------
-    public SortedMap headMap(Object toKey) {
-        SortedMap sub = ((SortedMap) maps[0]).headMap(toKey);
-        return new ViewMap(this, sub);
+    public SortedMap<K, V> headMap(K toKey) {
+        SortedMap<K, V> sub = ((SortedMap<K, V>) normalMap).headMap(toKey);
+        return new ViewMap<K, V>(this, sub);
     }
 
-    public SortedMap tailMap(Object fromKey) {
-        SortedMap sub = ((SortedMap) maps[0]).tailMap(fromKey);
-        return new ViewMap(this, sub);
+    public SortedMap<K, V> tailMap(K fromKey) {
+        SortedMap<K, V> sub = ((SortedMap<K, V>) normalMap).tailMap(fromKey);
+        return new ViewMap<K, V>(this, sub);
     }
 
-    public SortedMap subMap(Object fromKey, Object toKey) {
-        SortedMap sub = ((SortedMap) maps[0]).subMap(fromKey, toKey);
-        return new ViewMap(this, sub);
+    public SortedMap<K, V> subMap(K fromKey, K toKey) {
+        SortedMap<K, V> sub = ((SortedMap<K, V>) normalMap).subMap(fromKey, toKey);
+        return new ViewMap<K, V>(this, sub);
     }
-    
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public SortedBidiMap<V, K> inverseBidiMap() {
+        return (SortedBidiMap<V, K>) super.inverseBidiMap();
+    }
+
     //-----------------------------------------------------------------------
     /**
      * Internal sorted map view.
      */
-    protected static class ViewMap extends AbstractSortedMapDecorator {
+    protected static class ViewMap<K, V> extends AbstractSortedMapDecorator<K, V> {
         /** The parent bidi map. */
-        final DualTreeBidiMap bidi;
-        
+        final DualTreeBidiMap<K, V> bidi;
+
         /**
          * Constructor.
          * @param bidi  the parent bidi map
          * @param sm  the subMap sorted map
          */
-        protected ViewMap(DualTreeBidiMap bidi, SortedMap sm) {
+        protected ViewMap(DualTreeBidiMap<K, V> bidi, SortedMap<K, V> sm) {
             // the implementation is not great here...
-            // use the maps[0] as the filtered map, but maps[1] as the full map
+            // use the normalMap as the filtered map, but reverseMap as the full map
             // this forces containsValue and clear to be overridden
-            super((SortedMap) bidi.createBidiMap(sm, bidi.maps[1], bidi.inverseBidiMap));
-            this.bidi = (DualTreeBidiMap) map;
+            super(new DualTreeBidiMap<K, V>(sm, bidi.reverseMap, bidi.inverseBidiMap));
+            this.bidi = (DualTreeBidiMap<K, V>) decorated();
         }
-        
+
         public boolean containsValue(Object value) {
-            // override as default implementation jumps to [1]
-            return bidi.maps[0].containsValue(value);
+            // override as default implementation uses reverseMap
+            return decorated().normalMap.containsValue(value);
         }
-        
+
         public void clear() {
-            // override as default implementation jumps to [1]
-            for (Iterator it = keySet().iterator(); it.hasNext();) {
+            // override as default implementation uses reverseMap
+            for (Iterator<K> it = keySet().iterator(); it.hasNext();) {
                 it.next();
                 it.remove();
             }
         }
-        
-        public SortedMap headMap(Object toKey) {
-            return new ViewMap(bidi, super.headMap(toKey));
+
+        public SortedMap<K, V> headMap(K toKey) {
+            return new ViewMap<K, V>(decorated(), super.headMap(toKey));
+        }
+
+        public SortedMap<K, V> tailMap(K fromKey) {
+            return new ViewMap<K, V>(decorated(), super.tailMap(fromKey));
         }
 
-        public SortedMap tailMap(Object fromKey) {
-            return new ViewMap(bidi, super.tailMap(fromKey));
+        public SortedMap<K, V> subMap(K fromKey, K toKey) {
+            return new ViewMap<K, V>(decorated(), super.subMap(fromKey, toKey));
         }
 
-        public SortedMap subMap(Object fromKey, Object toKey) {
-            return new ViewMap(bidi, super.subMap(fromKey, toKey));
+        @Override
+        protected DualTreeBidiMap<K, V> decorated() {
+            return (DualTreeBidiMap<K, V>) super.decorated();
         }
     }
 
@@ -249,99 +275,101 @@ public class DualTreeBidiMap
     /**
      * Inner class MapIterator.
      */
-    protected static class BidiOrderedMapIterator implements OrderedMapIterator, ResettableIterator {
-        
+    protected static class BidiOrderedMapIterator<K, V> implements OrderedMapIterator<K, V>, ResettableIterator<K> {
+
         /** The parent map */
-        protected final AbstractDualBidiMap parent;
+        protected final AbstractDualBidiMap<K, V> parent;
+
         /** The iterator being decorated */
-        protected ListIterator iterator;
+        protected ListIterator<Map.Entry<K, V>> iterator;
+
         /** The last returned entry */
-        private Map.Entry last = null;
-        
+        private Map.Entry<K, V> last = null;
+
         /**
          * Constructor.
          * @param parent  the parent map
          */
-        protected BidiOrderedMapIterator(AbstractDualBidiMap parent) {
+        protected BidiOrderedMapIterator(AbstractDualBidiMap<K, V> parent) {
             super();
             this.parent = parent;
-            iterator = new ArrayList(parent.entrySet()).listIterator();
+            iterator = new ArrayList<Map.Entry<K, V>>(parent.entrySet()).listIterator();
         }
-        
+
         public boolean hasNext() {
             return iterator.hasNext();
         }
-        
-        public Object next() {
-            last = (Map.Entry) iterator.next();
+
+        public K next() {
+            last = iterator.next();
             return last.getKey();
         }
-        
+
         public boolean hasPrevious() {
             return iterator.hasPrevious();
         }
-        
-        public Object previous() {
-            last = (Map.Entry) iterator.previous();
+
+        public K previous() {
+            last = iterator.previous();
             return last.getKey();
         }
-        
+
         public void remove() {
             iterator.remove();
             parent.remove(last.getKey());
             last = null;
         }
-        
-        public Object getKey() {
+
+        public K getKey() {
             if (last == null) {
                 throw new IllegalStateException("Iterator getKey() can only be called after next() and before remove()");
             }
             return last.getKey();
         }
 
-        public Object getValue() {
+        public V getValue() {
             if (last == null) {
                 throw new IllegalStateException("Iterator getValue() can only be called after next() and before remove()");
             }
             return last.getValue();
         }
-        
-        public Object setValue(Object value) {
+
+        public V setValue(V value) {
             if (last == null) {
                 throw new IllegalStateException("Iterator setValue() can only be called after next() and before remove()");
             }
-            if (parent.maps[1].containsKey(value) &&
-                parent.maps[1].get(value) != last.getKey()) {
+            if (parent.reverseMap.containsKey(value) &&
+                parent.reverseMap.get(value) != last.getKey()) {
                 throw new IllegalArgumentException("Cannot use setValue() when the object being set is already in the map");
             }
             return parent.put(last.getKey(), value);
         }
-        
+
         public void reset() {
-            iterator = new ArrayList(parent.entrySet()).listIterator();
+            iterator = new ArrayList<Map.Entry<K, V>>(parent.entrySet()).listIterator();
             last = null;
         }
-        
+
         public String toString() {
             if (last != null) {
                 return "MapIterator[" + getKey() + "=" + getValue() + "]";
-            } else {
-                return "MapIterator[]";
             }
+            return "MapIterator[]";
         }
     }
-    
+
     // Serialization
     //-----------------------------------------------------------------------
     private void writeObject(ObjectOutputStream out) throws IOException {
         out.defaultWriteObject();
-        out.writeObject(maps[0]);
+        out.writeObject(normalMap);
     }
 
+    @SuppressWarnings("unchecked")
     private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
         in.defaultReadObject();
-        maps[0] = new TreeMap(comparator);
-        maps[1] = new TreeMap(comparator);
+        normalMap = new TreeMap(comparator);
+        reverseMap = new TreeMap(comparator);
         Map map = (Map) in.readObject();
         putAll(map);
     }