http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/ListOrderedMap.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/commons/collections/map/ListOrderedMap.java b/src/java/org/apache/commons/collections/map/ListOrderedMap.java index e27f914..c94f907 100644 --- a/src/java/org/apache/commons/collections/map/ListOrderedMap.java +++ b/src/java/org/apache/commons/collections/map/ListOrderedMap.java @@ -32,11 +32,10 @@ import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; -import org.apache.commons.collections.MapIterator; import org.apache.commons.collections.OrderedMap; import org.apache.commons.collections.OrderedMapIterator; import org.apache.commons.collections.ResettableIterator; -import org.apache.commons.collections.iterators.AbstractIteratorDecorator; +import org.apache.commons.collections.iterators.AbstractUntypedIteratorDecorator; import org.apache.commons.collections.keyvalue.AbstractMapEntry; import org.apache.commons.collections.list.UnmodifiableList; @@ -68,15 +67,15 @@ import org.apache.commons.collections.list.UnmodifiableList; * @author Stephen Colebourne * @author Matt Benson */ -public class ListOrderedMap - extends AbstractMapDecorator - implements OrderedMap, Serializable { +public class ListOrderedMap<K, V> + extends AbstractMapDecorator<K, V> + implements OrderedMap<K, V>, Serializable { /** Serialization version */ private static final long serialVersionUID = 2728177751851003750L; /** Internal list to hold the sequence of objects */ - protected final List insertOrder = new ArrayList(); + protected final List<K> insertOrder = new ArrayList<K>(); /** * Factory method to create an ordered map. @@ -86,8 +85,8 @@ public class ListOrderedMap * @param map the map to decorate, must not be null * @throws IllegalArgumentException if map is null */ - public static OrderedMap decorate(Map map) { - return new ListOrderedMap(map); + public static <K, V> OrderedMap<K, V> decorate(Map<K, V> map) { + return new ListOrderedMap<K, V>(map); } //----------------------------------------------------------------------- @@ -98,7 +97,7 @@ public class ListOrderedMap * @since Commons Collections 3.1 */ public ListOrderedMap() { - this(new HashMap()); + this(new HashMap<K, V>()); } /** @@ -107,7 +106,7 @@ public class ListOrderedMap * @param map the map to decorate, must not be null * @throws IllegalArgumentException if map is null */ - protected ListOrderedMap(Map map) { + protected ListOrderedMap(Map<K, V> map) { super(map); insertOrder.addAll(decorated().keySet()); } @@ -133,6 +132,7 @@ public class ListOrderedMap * @throws ClassNotFoundException * @since Commons Collections 3.1 */ + @SuppressWarnings("unchecked") private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); map = (Map) in.readObject(); @@ -140,12 +140,8 @@ public class ListOrderedMap // Implement OrderedMap //----------------------------------------------------------------------- - public MapIterator mapIterator() { - return orderedMapIterator(); - } - - public OrderedMapIterator orderedMapIterator() { - return new ListOrderedMapIterator(this); + public OrderedMapIterator<K, V> mapIterator() { + return new ListOrderedMapIterator<K, V>(this); } /** @@ -154,7 +150,7 @@ public class ListOrderedMap * @return the first key currently in this map * @throws NoSuchElementException if this map is empty */ - public Object firstKey() { + public K firstKey() { if (size() == 0) { throw new NoSuchElementException("Map is empty"); } @@ -167,7 +163,7 @@ public class ListOrderedMap * @return the last key currently in this map * @throws NoSuchElementException if this map is empty */ - public Object lastKey() { + public K lastKey() { if (size() == 0) { throw new NoSuchElementException("Map is empty"); } @@ -181,7 +177,7 @@ public class ListOrderedMap * @param key the key to find previous for * @return the next key, null if no match or at start */ - public Object nextKey(Object key) { + public K nextKey(Object key) { int index = insertOrder.indexOf(key); if (index >= 0 && index < size() - 1) { return insertOrder.get(index + 1); @@ -196,7 +192,7 @@ public class ListOrderedMap * @param key the key to find previous for * @return the previous key, null if no match or at start */ - public Object previousKey(Object key) { + public K previousKey(Object key) { int index = insertOrder.indexOf(key); if (index > 0) { return insertOrder.get(index - 1); @@ -205,27 +201,26 @@ public class ListOrderedMap } //----------------------------------------------------------------------- - public Object put(Object key, Object value) { + public V put(K key, V value) { if (decorated().containsKey(key)) { // re-adding doesn't change order return decorated().put(key, value); } else { // first add, so add to both map and list - Object result = decorated().put(key, value); + V result = decorated().put(key, value); insertOrder.add(key); return result; } } - public void putAll(Map map) { - for (Iterator it = map.entrySet().iterator(); it.hasNext();) { - Map.Entry entry = (Map.Entry) it.next(); + public void putAll(Map<? extends K, ? extends V> map) { + for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) { put(entry.getKey(), entry.getValue()); } } - public Object remove(Object key) { - Object result = decorated().remove(key); + public V remove(Object key) { + V result = decorated().remove(key); insertOrder.remove(key); return result; } @@ -244,8 +239,8 @@ public class ListOrderedMap * @see #keyList() * @return the fully modifiable collection view over the keys */ - public Set keySet() { - return new KeySetView(this); + public Set<K> keySet() { + return new KeySetView<K>(this); } /** @@ -258,7 +253,7 @@ public class ListOrderedMap * @return the unmodifiable list view over the keys * @since Commons Collections 3.2 */ - public List keyList() { + public List<K> keyList() { return UnmodifiableList.decorate(insertOrder); } @@ -273,8 +268,8 @@ public class ListOrderedMap * @see #valueList() * @return the fully modifiable collection view over the values */ - public Collection values() { - return new ValuesView(this); + public Collection<V> values() { + return new ValuesView<V>(this); } /** @@ -287,8 +282,8 @@ public class ListOrderedMap * @return the partially modifiable list view over the values * @since Commons Collections 3.2 */ - public List valueList() { - return new ValuesView(this); + public List<V> valueList() { + return new ValuesView<V>(this); } /** @@ -298,8 +293,8 @@ public class ListOrderedMap * * @return the fully modifiable set view over the entries */ - public Set entrySet() { - return new EntrySetView(this, this.insertOrder); + public Set<Map.Entry<K, V>> entrySet() { + return new EntrySetView<K, V>(this, this.insertOrder); } //----------------------------------------------------------------------- @@ -315,11 +310,9 @@ public class ListOrderedMap StringBuffer buf = new StringBuffer(); buf.append('{'); boolean first = true; - Iterator it = entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = (Map.Entry) it.next(); - Object key = entry.getKey(); - Object value = entry.getValue(); + for (Map.Entry<K, V> entry : entrySet()) { + K key = entry.getKey(); + V value = entry.getValue(); if (first) { first = false; } else { @@ -341,7 +334,7 @@ public class ListOrderedMap * @return the key at the specified index * @throws IndexOutOfBoundsException if the index is invalid */ - public Object get(int index) { + public K get(int index) { return insertOrder.get(index); } @@ -352,7 +345,7 @@ public class ListOrderedMap * @return the key at the specified index * @throws IndexOutOfBoundsException if the index is invalid */ - public Object getValue(int index) { + public V getValue(int index) { return get(insertOrder.get(index)); } @@ -374,8 +367,8 @@ public class ListOrderedMap * @throws IndexOutOfBoundsException if the index is invalid * @since Commons Collections 3.2 */ - public Object setValue(int index, Object value) { - Object key = insertOrder.get(index); + public V setValue(int index, V value) { + K key = insertOrder.get(index); return put(key, value); } @@ -398,10 +391,10 @@ public class ListOrderedMap * @throws IndexOutOfBoundsException if the index is out of range * @since Commons Collections 3.2 */ - public Object put(int index, Object key, Object value) { - Map m = decorated(); + public V put(int index, K key, V value) { + Map<K, V> m = decorated(); if (m.containsKey(key)) { - Object result = m.remove(key); + V result = m.remove(key); int pos = insertOrder.indexOf(key); insertOrder.remove(pos); if (pos < index) { @@ -424,7 +417,7 @@ public class ListOrderedMap * @return the removed value, or <code>null</code> if none existed * @throws IndexOutOfBoundsException if the index is invalid */ - public Object remove(int index) { + public V remove(int index) { return remove(get(index)); } @@ -445,17 +438,18 @@ public class ListOrderedMap * @see #keySet() * @return The ordered list of keys. */ - public List asList() { + public List<K> asList() { return keyList(); } //----------------------------------------------------------------------- - static class ValuesView extends AbstractList { - private final ListOrderedMap parent; + static class ValuesView<V> extends AbstractList<V> { + private final ListOrderedMap<Object, V> parent; - ValuesView(ListOrderedMap parent) { + @SuppressWarnings("unchecked") + ValuesView(ListOrderedMap<?, V> parent) { super(); - this.parent = parent; + this.parent = (ListOrderedMap<Object, V>) parent; } public int size() { @@ -470,34 +464,35 @@ public class ListOrderedMap this.parent.clear(); } - public Iterator iterator() { - return new AbstractIteratorDecorator(parent.entrySet().iterator()) { - public Object next() { - return ((Map.Entry) iterator.next()).getValue(); + public Iterator<V> iterator() { + return new AbstractUntypedIteratorDecorator<Map.Entry<Object, V>, V>(parent.entrySet().iterator()) { + public V next() { + return getIterator().next().getValue(); } }; } - public Object get(int index) { + public V get(int index) { return this.parent.getValue(index); } - public Object set(int index, Object value) { + public V set(int index, V value) { return this.parent.setValue(index, value); } - public Object remove(int index) { + public V remove(int index) { return this.parent.remove(index); } } //----------------------------------------------------------------------- - static class KeySetView extends AbstractSet { - private final ListOrderedMap parent; + static class KeySetView<K> extends AbstractSet<K> { + private final ListOrderedMap<K, Object> parent; - KeySetView(ListOrderedMap parent) { + @SuppressWarnings("unchecked") + KeySetView(ListOrderedMap<K, ?> parent) { super(); - this.parent = parent; + this.parent = (ListOrderedMap<K, Object>) parent; } public int size() { @@ -512,28 +507,28 @@ public class ListOrderedMap this.parent.clear(); } - public Iterator iterator() { - return new AbstractIteratorDecorator(parent.entrySet().iterator()) { - public Object next() { - return ((Map.Entry) super.next()).getKey(); + public Iterator<K> iterator() { + return new AbstractUntypedIteratorDecorator<Map.Entry<K, Object>, K>(parent.entrySet().iterator()) { + public K next() { + return getIterator().next().getKey(); } }; } } //----------------------------------------------------------------------- - static class EntrySetView extends AbstractSet { - private final ListOrderedMap parent; - private final List insertOrder; - private Set entrySet; + static class EntrySetView<K, V> extends AbstractSet<Map.Entry<K, V>> { + private final ListOrderedMap<K, V> parent; + private final List<K> insertOrder; + private Set<Map.Entry<K, V>> entrySet; - public EntrySetView(ListOrderedMap parent, List insertOrder) { + public EntrySetView(ListOrderedMap<K, V> parent, List<K> insertOrder) { super(); this.parent = parent; this.insertOrder = insertOrder; } - private Set getEntrySet() { + private Set<Map.Entry<K, V>> getEntrySet() { if (entrySet == null) { entrySet = parent.decorated().entrySet(); } @@ -551,16 +546,17 @@ public class ListOrderedMap return getEntrySet().contains(obj); } - public boolean containsAll(Collection coll) { + public boolean containsAll(Collection<?> coll) { return getEntrySet().containsAll(coll); } + @SuppressWarnings("unchecked") public boolean remove(Object obj) { if (obj instanceof Map.Entry == false) { return false; } if (getEntrySet().contains(obj)) { - Object key = ((Map.Entry) obj).getKey(); + Object key = ((Map.Entry<K, V>) obj).getKey(); parent.remove(key); return true; } @@ -570,14 +566,14 @@ public class ListOrderedMap public void clear() { this.parent.clear(); } - + public boolean equals(Object obj) { if (obj == this) { return true; } return getEntrySet().equals(obj); } - + public int hashCode() { return getEntrySet().hashCode(); } @@ -585,25 +581,25 @@ public class ListOrderedMap public String toString() { return getEntrySet().toString(); } - - public Iterator iterator() { - return new ListOrderedIterator(parent, insertOrder); + + public Iterator<Map.Entry<K, V>> iterator() { + return new ListOrderedIterator<K, V>(parent, insertOrder); } } - + //----------------------------------------------------------------------- - static class ListOrderedIterator extends AbstractIteratorDecorator { - private final ListOrderedMap parent; - private Object last = null; + static class ListOrderedIterator<K, V> extends AbstractUntypedIteratorDecorator<K, Map.Entry<K, V>> { + private final ListOrderedMap<K, V> parent; + private K last = null; - ListOrderedIterator(ListOrderedMap parent, List insertOrder) { + ListOrderedIterator(ListOrderedMap<K, V> parent, List<K> insertOrder) { super(insertOrder.iterator()); this.parent = parent; } - - public Object next() { - last = super.next(); - return new ListOrderedMapEntry(parent, last); + + public Map.Entry<K, V> next() { + last = getIterator().next(); + return new ListOrderedMapEntry<K, V>(parent, last); } public void remove() { @@ -611,43 +607,43 @@ public class ListOrderedMap parent.decorated().remove(last); } } - + //----------------------------------------------------------------------- - static class ListOrderedMapEntry extends AbstractMapEntry { - private final ListOrderedMap parent; - - ListOrderedMapEntry(ListOrderedMap parent, Object key) { + static class ListOrderedMapEntry<K, V> extends AbstractMapEntry<K, V> { + private final ListOrderedMap<K, V> parent; + + ListOrderedMapEntry(ListOrderedMap<K, V> parent, K key) { super(key, null); this.parent = parent; } - - public Object getValue() { + + public V getValue() { return parent.get(key); } - public Object setValue(Object value) { + public V setValue(V value) { return parent.decorated().put(key, value); } } //----------------------------------------------------------------------- - static class ListOrderedMapIterator implements OrderedMapIterator, ResettableIterator { - private final ListOrderedMap parent; - private ListIterator iterator; - private Object last = null; + static class ListOrderedMapIterator<K, V> implements OrderedMapIterator<K, V>, ResettableIterator<K> { + private final ListOrderedMap<K, V> parent; + private ListIterator<K> iterator; + private K last = null; private boolean readable = false; - - ListOrderedMapIterator(ListOrderedMap parent) { + + ListOrderedMapIterator(ListOrderedMap<K, V> parent) { super(); this.parent = parent; this.iterator = parent.insertOrder.listIterator(); } - + public boolean hasNext() { return iterator.hasNext(); } - - public Object next() { + + public K next() { last = iterator.next(); readable = true; return last; @@ -656,13 +652,13 @@ public class ListOrderedMap public boolean hasPrevious() { return iterator.hasPrevious(); } - - public Object previous() { + + public K previous() { last = iterator.previous(); readable = true; return last; } - + public void remove() { if (readable == false) { throw new IllegalStateException(AbstractHashedMap.REMOVE_INVALID); @@ -671,41 +667,40 @@ public class ListOrderedMap parent.map.remove(last); readable = false; } - - public Object getKey() { + + public K getKey() { if (readable == false) { throw new IllegalStateException(AbstractHashedMap.GETKEY_INVALID); } return last; } - public Object getValue() { + public V getValue() { if (readable == false) { throw new IllegalStateException(AbstractHashedMap.GETVALUE_INVALID); } return parent.get(last); } - - public Object setValue(Object value) { + + public V setValue(V value) { if (readable == false) { throw new IllegalStateException(AbstractHashedMap.SETVALUE_INVALID); } return parent.map.put(last, value); } - + public void reset() { iterator = parent.insertOrder.listIterator(); last = null; readable = false; } - + public String toString() { if (readable == true) { return "Iterator[" + getKey() + "=" + getValue() + "]"; - } else { - return "Iterator[]"; } + return "Iterator[]"; } } - + }
http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/MultiKeyMap.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/commons/collections/map/MultiKeyMap.java b/src/java/org/apache/commons/collections/map/MultiKeyMap.java index b8af692..563e7bd 100644 --- a/src/java/org/apache/commons/collections/map/MultiKeyMap.java +++ b/src/java/org/apache/commons/collections/map/MultiKeyMap.java @@ -17,10 +17,7 @@ package org.apache.commons.collections.map; import java.io.Serializable; -import java.util.Collection; -import java.util.Iterator; import java.util.Map; -import java.util.Set; import org.apache.commons.collections.IterableMap; import org.apache.commons.collections.MapIterator; @@ -77,14 +74,15 @@ import org.apache.commons.collections.keyvalue.MultiKey; * * @author Stephen Colebourne */ -public class MultiKeyMap - implements IterableMap, Serializable { +public class MultiKeyMap<K, V> extends AbstractMapDecorator<MultiKey<? extends K>, V> + implements IterableMap<MultiKey<? extends K>, V>, Serializable { /** Serialisation version */ private static final long serialVersionUID = -1788199231038721040L; /** The decorated map */ - protected final AbstractHashedMap map; + //keep this member around for serialization BC with older Collections releases assuming we want to do that + protected AbstractHashedMap<MultiKey<? extends K>, V> map; //----------------------------------------------------------------------- /** @@ -94,14 +92,14 @@ public class MultiKeyMap * @param map the map to decorate, not null * @throws IllegalArgumentException if the map is null or not empty */ - public static MultiKeyMap decorate(AbstractHashedMap map) { + public static <K, V> MultiKeyMap<K, V> decorate(AbstractHashedMap<MultiKey<? extends K>, V> map) { if (map == null) { throw new IllegalArgumentException("Map must not be null"); } if (map.size() > 0) { throw new IllegalArgumentException("Map must be empty"); } - return new MultiKeyMap(map); + return new MultiKeyMap<K, V>(map); } //----------------------------------------------------------------------- @@ -109,8 +107,7 @@ public class MultiKeyMap * Constructs a new MultiKeyMap that decorates a <code>HashedMap</code>. */ public MultiKeyMap() { - super(); - map = new HashedMap(); + this(new HashedMap<MultiKey<? extends K>, V>()); } /** @@ -121,8 +118,8 @@ public class MultiKeyMap * * @param map the map to decorate */ - protected MultiKeyMap(AbstractHashedMap map) { - super(); + protected MultiKeyMap(AbstractHashedMap<MultiKey<? extends K>, V> map) { + super(map); this.map = map; } @@ -134,9 +131,9 @@ public class MultiKeyMap * @param key2 the second key * @return the mapped value, null if no match */ - public Object get(Object key1, Object key2) { + public V get(Object key1, Object key2) { int hashCode = hash(key1, key2); - AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)]; + AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[decorated().hashIndex(hashCode, decorated().data.length)]; while (entry != null) { if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2)) { return entry.getValue(); @@ -155,7 +152,7 @@ public class MultiKeyMap */ public boolean containsKey(Object key1, Object key2) { int hashCode = hash(key1, key2); - AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)]; + AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[decorated().hashIndex(hashCode, decorated().data.length)]; while (entry != null) { if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2)) { return true; @@ -173,20 +170,19 @@ public class MultiKeyMap * @param value the value to store * @return the value previously mapped to this combined key, null if none */ - public Object put(Object key1, Object key2, Object value) { + public V put(K key1, K key2, V value) { int hashCode = hash(key1, key2); - int index = map.hashIndex(hashCode, map.data.length); - AbstractHashedMap.HashEntry entry = map.data[index]; + int index = decorated().hashIndex(hashCode, decorated().data.length); + AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[index]; while (entry != null) { if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2)) { - Object oldValue = entry.getValue(); - map.updateEntry(entry, value); + V oldValue = entry.getValue(); + decorated().updateEntry(entry, value); return oldValue; } entry = entry.next; } - - map.addMapping(index, hashCode, new MultiKey(key1, key2), value); + decorated().addMapping(index, hashCode, new MultiKey<K>(key1, key2), value); return null; } @@ -197,15 +193,15 @@ public class MultiKeyMap * @param key2 the second key * @return the value mapped to the removed key, null if key not in map */ - public Object remove(Object key1, Object key2) { + public V remove(Object key1, Object key2) { int hashCode = hash(key1, key2); - int index = map.hashIndex(hashCode, map.data.length); - AbstractHashedMap.HashEntry entry = map.data[index]; - AbstractHashedMap.HashEntry previous = null; + int index = decorated().hashIndex(hashCode, decorated().data.length); + AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[index]; + AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> previous = null; while (entry != null) { if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2)) { - Object oldValue = entry.getValue(); - map.removeMapping(entry, index, previous); + V oldValue = entry.getValue(); + decorated().removeMapping(entry, index, previous); return oldValue; } previous = entry; @@ -244,12 +240,13 @@ public class MultiKeyMap * @param key2 the second key * @return true if the key matches */ - protected boolean isEqualKey(AbstractHashedMap.HashEntry entry, Object key1, Object key2) { - MultiKey multi = (MultiKey) entry.getKey(); + protected boolean isEqualKey(AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry, + Object key1, Object key2) { + MultiKey<? extends K> multi = entry.getKey(); return multi.size() == 2 && - (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) && - (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1))); + (key1 == multi.getKey(0) || key1 != null && key1.equals(multi.getKey(0))) && + (key2 == multi.getKey(1) || key1 != null && key2.equals(multi.getKey(1))); } //----------------------------------------------------------------------- @@ -261,9 +258,9 @@ public class MultiKeyMap * @param key3 the third key * @return the mapped value, null if no match */ - public Object get(Object key1, Object key2, Object key3) { + public V get(Object key1, Object key2, Object key3) { int hashCode = hash(key1, key2, key3); - AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)]; + AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[decorated().hashIndex(hashCode, decorated().data.length)]; while (entry != null) { if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3)) { return entry.getValue(); @@ -283,7 +280,7 @@ public class MultiKeyMap */ public boolean containsKey(Object key1, Object key2, Object key3) { int hashCode = hash(key1, key2, key3); - AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)]; + AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[decorated().hashIndex(hashCode, decorated().data.length)]; while (entry != null) { if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3)) { return true; @@ -302,20 +299,19 @@ public class MultiKeyMap * @param value the value to store * @return the value previously mapped to this combined key, null if none */ - public Object put(Object key1, Object key2, Object key3, Object value) { + public V put(K key1, K key2, K key3, V value) { int hashCode = hash(key1, key2, key3); - int index = map.hashIndex(hashCode, map.data.length); - AbstractHashedMap.HashEntry entry = map.data[index]; + int index = decorated().hashIndex(hashCode, decorated().data.length); + AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[index]; while (entry != null) { if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3)) { - Object oldValue = entry.getValue(); - map.updateEntry(entry, value); + V oldValue = entry.getValue(); + decorated().updateEntry(entry, value); return oldValue; } entry = entry.next; } - - map.addMapping(index, hashCode, new MultiKey(key1, key2, key3), value); + decorated().addMapping(index, hashCode, new MultiKey<K>(key1, key2, key3), value); return null; } @@ -327,15 +323,15 @@ public class MultiKeyMap * @param key3 the third key * @return the value mapped to the removed key, null if key not in map */ - public Object remove(Object key1, Object key2, Object key3) { + public V remove(Object key1, Object key2, Object key3) { int hashCode = hash(key1, key2, key3); - int index = map.hashIndex(hashCode, map.data.length); - AbstractHashedMap.HashEntry entry = map.data[index]; - AbstractHashedMap.HashEntry previous = null; + int index = decorated().hashIndex(hashCode, decorated().data.length); + AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[index]; + AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> previous = null; while (entry != null) { if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3)) { - Object oldValue = entry.getValue(); - map.removeMapping(entry, index, previous); + V oldValue = entry.getValue(); + decorated().removeMapping(entry, index, previous); return oldValue; } previous = entry; @@ -379,13 +375,13 @@ public class MultiKeyMap * @param key3 the third key * @return true if the key matches */ - protected boolean isEqualKey(AbstractHashedMap.HashEntry entry, Object key1, Object key2, Object key3) { - MultiKey multi = (MultiKey) entry.getKey(); + protected boolean isEqualKey(AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry, Object key1, Object key2, Object key3) { + MultiKey<? extends K> multi = entry.getKey(); return multi.size() == 3 && - (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) && - (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1))) && - (key3 == null ? multi.getKey(2) == null : key3.equals(multi.getKey(2))); + (key1 == multi.getKey(0) || key1 != null && key1.equals(multi.getKey(0))) && + (key2 == multi.getKey(1) || key2 != null && key2.equals(multi.getKey(1))) && + (key3 == multi.getKey(2) || key3 != null && key3.equals(multi.getKey(2))); } //----------------------------------------------------------------------- @@ -398,9 +394,9 @@ public class MultiKeyMap * @param key4 the fourth key * @return the mapped value, null if no match */ - public Object get(Object key1, Object key2, Object key3, Object key4) { + public V get(Object key1, Object key2, Object key3, Object key4) { int hashCode = hash(key1, key2, key3, key4); - AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)]; + AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[decorated().hashIndex(hashCode, decorated().data.length)]; while (entry != null) { if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4)) { return entry.getValue(); @@ -421,7 +417,7 @@ public class MultiKeyMap */ public boolean containsKey(Object key1, Object key2, Object key3, Object key4) { int hashCode = hash(key1, key2, key3, key4); - AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)]; + AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[decorated().hashIndex(hashCode, decorated().data.length)]; while (entry != null) { if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4)) { return true; @@ -441,20 +437,19 @@ public class MultiKeyMap * @param value the value to store * @return the value previously mapped to this combined key, null if none */ - public Object put(Object key1, Object key2, Object key3, Object key4, Object value) { + public V put(K key1, K key2, K key3, K key4, V value) { int hashCode = hash(key1, key2, key3, key4); - int index = map.hashIndex(hashCode, map.data.length); - AbstractHashedMap.HashEntry entry = map.data[index]; + int index = decorated().hashIndex(hashCode, decorated().data.length); + AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[index]; while (entry != null) { if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4)) { - Object oldValue = entry.getValue(); - map.updateEntry(entry, value); + V oldValue = entry.getValue(); + decorated().updateEntry(entry, value); return oldValue; } entry = entry.next; } - - map.addMapping(index, hashCode, new MultiKey(key1, key2, key3, key4), value); + decorated().addMapping(index, hashCode, new MultiKey<K>(key1, key2, key3, key4), value); return null; } @@ -467,15 +462,15 @@ public class MultiKeyMap * @param key4 the fourth key * @return the value mapped to the removed key, null if key not in map */ - public Object remove(Object key1, Object key2, Object key3, Object key4) { + public V remove(Object key1, Object key2, Object key3, Object key4) { int hashCode = hash(key1, key2, key3, key4); - int index = map.hashIndex(hashCode, map.data.length); - AbstractHashedMap.HashEntry entry = map.data[index]; - AbstractHashedMap.HashEntry previous = null; + int index = decorated().hashIndex(hashCode, decorated().data.length); + AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[index]; + AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> previous = null; while (entry != null) { if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4)) { - Object oldValue = entry.getValue(); - map.removeMapping(entry, index, previous); + V oldValue = entry.getValue(); + decorated().removeMapping(entry, index, previous); return oldValue; } previous = entry; @@ -524,14 +519,14 @@ public class MultiKeyMap * @param key4 the fourth key * @return true if the key matches */ - protected boolean isEqualKey(AbstractHashedMap.HashEntry entry, Object key1, Object key2, Object key3, Object key4) { - MultiKey multi = (MultiKey) entry.getKey(); + protected boolean isEqualKey(AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry, Object key1, Object key2, Object key3, Object key4) { + MultiKey<? extends K> multi = entry.getKey(); return multi.size() == 4 && - (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) && - (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1))) && - (key3 == null ? multi.getKey(2) == null : key3.equals(multi.getKey(2))) && - (key4 == null ? multi.getKey(3) == null : key4.equals(multi.getKey(3))); + (key1 == multi.getKey(0) || key1 != null && key1.equals(multi.getKey(0))) && + (key2 == multi.getKey(1) || key2 != null && key2.equals(multi.getKey(1))) && + (key3 == multi.getKey(2) || key3 != null && key3.equals(multi.getKey(2))) && + (key4 == multi.getKey(3) || key4 != null && key4.equals(multi.getKey(3))); } //----------------------------------------------------------------------- @@ -545,9 +540,9 @@ public class MultiKeyMap * @param key5 the fifth key * @return the mapped value, null if no match */ - public Object get(Object key1, Object key2, Object key3, Object key4, Object key5) { + public V get(Object key1, Object key2, Object key3, Object key4, Object key5) { int hashCode = hash(key1, key2, key3, key4, key5); - AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)]; + AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[decorated().hashIndex(hashCode, decorated().data.length)]; while (entry != null) { if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4, key5)) { return entry.getValue(); @@ -569,7 +564,7 @@ public class MultiKeyMap */ public boolean containsKey(Object key1, Object key2, Object key3, Object key4, Object key5) { int hashCode = hash(key1, key2, key3, key4, key5); - AbstractHashedMap.HashEntry entry = map.data[map.hashIndex(hashCode, map.data.length)]; + AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[decorated().hashIndex(hashCode, decorated().data.length)]; while (entry != null) { if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4, key5)) { return true; @@ -590,20 +585,19 @@ public class MultiKeyMap * @param value the value to store * @return the value previously mapped to this combined key, null if none */ - public Object put(Object key1, Object key2, Object key3, Object key4, Object key5, Object value) { + public V put(K key1, K key2, K key3, K key4, K key5, V value) { int hashCode = hash(key1, key2, key3, key4, key5); - int index = map.hashIndex(hashCode, map.data.length); - AbstractHashedMap.HashEntry entry = map.data[index]; + int index = decorated().hashIndex(hashCode, decorated().data.length); + AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[index]; while (entry != null) { if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4, key5)) { - Object oldValue = entry.getValue(); - map.updateEntry(entry, value); + V oldValue = entry.getValue(); + decorated().updateEntry(entry, value); return oldValue; } entry = entry.next; } - - map.addMapping(index, hashCode, new MultiKey(key1, key2, key3, key4, key5), value); + decorated().addMapping(index, hashCode, new MultiKey<K>(key1, key2, key3, key4, key5), value); return null; } @@ -617,15 +611,15 @@ public class MultiKeyMap * @param key5 the fifth key * @return the value mapped to the removed key, null if key not in map */ - public Object remove(Object key1, Object key2, Object key3, Object key4, Object key5) { + public V remove(Object key1, Object key2, Object key3, Object key4, Object key5) { int hashCode = hash(key1, key2, key3, key4, key5); - int index = map.hashIndex(hashCode, map.data.length); - AbstractHashedMap.HashEntry entry = map.data[index]; - AbstractHashedMap.HashEntry previous = null; + int index = decorated().hashIndex(hashCode, decorated().data.length); + AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry = decorated().data[index]; + AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> previous = null; while (entry != null) { if (entry.hashCode == hashCode && isEqualKey(entry, key1, key2, key3, key4, key5)) { - Object oldValue = entry.getValue(); - map.removeMapping(entry, index, previous); + V oldValue = entry.getValue(); + decorated().removeMapping(entry, index, previous); return oldValue; } previous = entry; @@ -679,15 +673,16 @@ public class MultiKeyMap * @param key5 the fifth key * @return true if the key matches */ - protected boolean isEqualKey(AbstractHashedMap.HashEntry entry, Object key1, Object key2, Object key3, Object key4, Object key5) { - MultiKey multi = (MultiKey) entry.getKey(); + protected boolean isEqualKey(AbstractHashedMap.HashEntry<MultiKey<? extends K>, V> entry, + Object key1, Object key2, Object key3, Object key4, Object key5) { + MultiKey<? extends K> multi = entry.getKey(); return multi.size() == 5 && - (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) && - (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1))) && - (key3 == null ? multi.getKey(2) == null : key3.equals(multi.getKey(2))) && - (key4 == null ? multi.getKey(3) == null : key4.equals(multi.getKey(3))) && - (key5 == null ? multi.getKey(4) == null : key5.equals(multi.getKey(4))); + (key1 == multi.getKey(0) || key1 != null && key1.equals(multi.getKey(0))) && + (key2 == multi.getKey(1) || key2 != null && key2.equals(multi.getKey(1))) && + (key3 == multi.getKey(2) || key3 != null && key3.equals(multi.getKey(2))) && + (key4 == multi.getKey(3) || key4 != null && key4.equals(multi.getKey(3))) && + (key5 == multi.getKey(4) || key5 != null && key5.equals(multi.getKey(4))); } //----------------------------------------------------------------------- @@ -702,9 +697,9 @@ public class MultiKeyMap */ public boolean removeAll(Object key1) { boolean modified = false; - MapIterator it = mapIterator(); + MapIterator<MultiKey<? extends K>, V> it = mapIterator(); while (it.hasNext()) { - MultiKey multi = (MultiKey) it.next(); + MultiKey<? extends K> multi = it.next(); if (multi.size() >= 1 && (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0)))) { it.remove(); @@ -726,9 +721,9 @@ public class MultiKeyMap */ public boolean removeAll(Object key1, Object key2) { boolean modified = false; - MapIterator it = mapIterator(); + MapIterator<MultiKey<? extends K>, V> it = mapIterator(); while (it.hasNext()) { - MultiKey multi = (MultiKey) it.next(); + MultiKey<? extends K> multi = it.next(); if (multi.size() >= 2 && (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) && (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1)))) { @@ -752,9 +747,9 @@ public class MultiKeyMap */ public boolean removeAll(Object key1, Object key2, Object key3) { boolean modified = false; - MapIterator it = mapIterator(); + MapIterator<MultiKey<? extends K>, V> it = mapIterator(); while (it.hasNext()) { - MultiKey multi = (MultiKey) it.next(); + MultiKey<? extends K> multi = it.next(); if (multi.size() >= 3 && (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) && (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1))) && @@ -780,9 +775,9 @@ public class MultiKeyMap */ public boolean removeAll(Object key1, Object key2, Object key3, Object key4) { boolean modified = false; - MapIterator it = mapIterator(); + MapIterator<MultiKey<? extends K>, V> it = mapIterator(); while (it.hasNext()) { - MultiKey multi = (MultiKey) it.next(); + MultiKey<? extends K> multi = it.next(); if (multi.size() >= 4 && (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) && (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1))) && @@ -801,13 +796,10 @@ public class MultiKeyMap * * @param key the key to check */ - protected void checkKey(Object key) { + protected void checkKey(MultiKey<?> key) { if (key == null) { throw new NullPointerException("Key must not be null"); } - if (key instanceof MultiKey == false) { - throw new ClassCastException("Key must be a MultiKey"); - } } /** @@ -815,8 +807,8 @@ public class MultiKeyMap * * @return a shallow clone */ - public Object clone() { - return new MultiKeyMap((AbstractHashedMap) map.clone()); + public MultiKeyMap<K, V> clone() { + return new MultiKeyMap<K, V>(decorated().clone()); } /** @@ -829,9 +821,9 @@ public class MultiKeyMap * @throws NullPointerException if the key is null * @throws ClassCastException if the key is not a MultiKey */ - public Object put(Object key, Object value) { + public V put(MultiKey<? extends K> key, V value) { checkKey(key); - return map.put(key, value); + return super.put(key, value); } /** @@ -842,72 +834,24 @@ public class MultiKeyMap * @throws NullPointerException if the mapToCopy or any key within is null * @throws ClassCastException if any key in mapToCopy is not a MultiKey */ - public void putAll(Map mapToCopy) { - for (Iterator it = mapToCopy.keySet().iterator(); it.hasNext();) { - Object key = it.next(); + @Override + public void putAll(Map<? extends MultiKey<? extends K>, ? extends V> mapToCopy) { + for (MultiKey<? extends K> key : mapToCopy.keySet()) { checkKey(key); } - map.putAll(mapToCopy); + super.putAll(mapToCopy); } //----------------------------------------------------------------------- - public MapIterator mapIterator() { - return map.mapIterator(); - } - - public int size() { - return map.size(); - } - - public boolean isEmpty() { - return map.isEmpty(); - } - - public boolean containsKey(Object key) { - return map.containsKey(key); - } - - public boolean containsValue(Object value) { - return map.containsValue(value); - } - - public Object get(Object key) { - return map.get(key); - } - - public Object remove(Object key) { - return map.remove(key); - } - - public void clear() { - map.clear(); + public MapIterator<MultiKey<? extends K>, V> mapIterator() { + return decorated().mapIterator(); } - public Set keySet() { - return map.keySet(); - } - - public Collection values() { - return map.values(); - } - - public Set entrySet() { - return map.entrySet(); - } - - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - return map.equals(obj); - } - - public int hashCode() { - return map.hashCode(); - } - - public String toString() { - return map.toString(); + /** + * {@inheritDoc} + */ + @Override + protected AbstractHashedMap<MultiKey<? extends K>, V> decorated() { + return map; } - } http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/MultiValueMap.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/commons/collections/map/MultiValueMap.java b/src/java/org/apache/commons/collections/map/MultiValueMap.java index 04f6522..b7b7059 100644 --- a/src/java/org/apache/commons/collections/map/MultiValueMap.java +++ b/src/java/org/apache/commons/collections/map/MultiValueMap.java @@ -24,6 +24,7 @@ import java.util.Iterator; import java.util.Map; import java.util.Set; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.Factory; import org.apache.commons.collections.FunctorException; import org.apache.commons.collections.MultiMap; @@ -61,12 +62,12 @@ import org.apache.commons.collections.iterators.IteratorChain; * @version $Revision$ $Date$ * @since Commons Collections 3.2 */ -public class MultiValueMap extends AbstractMapDecorator implements MultiMap { +public class MultiValueMap<K, V> extends AbstractMapDecorator<K, Object> implements MultiMap<K, V> { /** The factory for creating value collections. */ - private final Factory collectionFactory; + private final Factory<? extends Collection<V>> collectionFactory; /** The cached values. */ - private transient Collection values; + private transient Collection<V> values; /** * Creates a map which wraps the given map and @@ -74,8 +75,9 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap { * * @param map the map to wrap */ - public static MultiValueMap decorate(Map map) { - return new MultiValueMap(map, new ReflectionFactory(ArrayList.class)); + @SuppressWarnings("unchecked") + public static <K, V> MultiValueMap<K, V> decorate(Map<K, ? super Collection<V>> map) { + return MultiValueMap.<K, V, ArrayList>decorate((Map<K, ? super Collection>) map, ArrayList.class); } /** @@ -85,8 +87,8 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap { * @param map the map to wrap * @param collectionClass the type of the collection class */ - public static MultiValueMap decorate(Map map, Class collectionClass) { - return new MultiValueMap(map, new ReflectionFactory(collectionClass)); + public static <K, V, C extends Collection<V>> MultiValueMap<K, V> decorate(Map<K, ? super C> map, Class<C> collectionClass) { + return new MultiValueMap<K, V>(map, new ReflectionFactory<C>(collectionClass)); } /** @@ -96,8 +98,8 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap { * @param map the map to decorate * @param collectionFactory the collection factory (must return a Collection object). */ - public static MultiValueMap decorate(Map map, Factory collectionFactory) { - return new MultiValueMap(map, collectionFactory); + public static <K, V, C extends Collection<V>> MultiValueMap<K, V> decorate(Map<K, ? super C> map, Factory<C> collectionFactory) { + return new MultiValueMap<K, V>(map, collectionFactory); } //----------------------------------------------------------------------- @@ -105,6 +107,7 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap { * Creates a MultiValueMap based on a <code>HashMap</code> and * storing the multiple values in an <code>ArrayList</code>. */ + @SuppressWarnings("unchecked") public MultiValueMap() { this(new HashMap(), new ReflectionFactory(ArrayList.class)); } @@ -116,8 +119,9 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap { * @param map the map to decorate * @param collectionFactory the collection factory which must return a Collection instance */ - protected MultiValueMap(Map map, Factory collectionFactory) { - super(map); + @SuppressWarnings("unchecked") + protected <C extends Collection<V>> MultiValueMap(Map<K, ? super C> map, Factory<C> collectionFactory) { + super((Map<K, Object>) map); if (collectionFactory == null) { throw new IllegalArgumentException("The factory must not be null"); } @@ -153,8 +157,9 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap { * @param value the value to remove * @return the value removed (which was passed in), null if nothing removed */ - public Object remove(Object key, Object value) { - Collection valuesForKey = getCollection(key); + @SuppressWarnings("unchecked") + public V remove(Object key, Object value) { + Collection<V> valuesForKey = getCollection(key); if (valuesForKey == null) { return null; } @@ -165,7 +170,7 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap { if (valuesForKey.isEmpty()) { remove(key); } - return value; + return (V) value; } /** @@ -176,17 +181,14 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap { * @param value the value to search for * @return true if the map contains the value */ + @SuppressWarnings("unchecked") public boolean containsValue(Object value) { - Set pairs = decorated().entrySet(); - if (pairs == null) { - return false; - } - Iterator pairsIterator = pairs.iterator(); - while (pairsIterator.hasNext()) { - Map.Entry keyValuePair = (Map.Entry) pairsIterator.next(); - Collection coll = (Collection) keyValuePair.getValue(); - if (coll.contains(value)) { - return true; + Set<Map.Entry<K, Object>> pairs = decorated().entrySet(); + if (pairs != null) { + for (Map.Entry<K, Object> entry : pairs) { + if (((Collection<V>) entry.getValue()).contains(value)) { + return true; + } } } return false; @@ -202,19 +204,20 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap { * @param value the value to add to the collection at the key * @return the value added if the map changed and null if the map did not change */ - public Object put(Object key, Object value) { + @SuppressWarnings("unchecked") + public Object put(K key, Object value) { boolean result = false; - Collection coll = getCollection(key); + Collection<V> coll = getCollection(key); if (coll == null) { coll = createCollection(1); // might produce a non-empty collection - coll.add(value); + coll.add((V) value); if (coll.size() > 0) { // only add if non-zero size to maintain class state decorated().put(key, coll); result = true; // map definitely changed } } else { - result = coll.add(value); + result = coll.add((V) value); } return (result ? value : null); } @@ -230,17 +233,15 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap { * * @param map the map to copy (either a normal or multi map) */ - public void putAll(Map map) { + @SuppressWarnings("unchecked") + public void putAll(Map<? extends K, ?> map) { if (map instanceof MultiMap) { - for (Iterator it = map.entrySet().iterator(); it.hasNext();) { - Map.Entry entry = (Map.Entry) it.next(); - Collection coll = (Collection) entry.getValue(); - putAll(entry.getKey(), coll); + for (Map.Entry<? extends K, Object> entry : ((MultiMap<? extends K, V>) map).entrySet()) { + putAll(entry.getKey(), (Collection<V>) entry.getValue()); } } else { - for (Iterator it = map.entrySet().iterator(); it.hasNext();) { - Map.Entry entry = (Map.Entry) it.next(); - put(entry.getKey(), entry.getValue()); + for (Map.Entry<? extends K, ?> entry : map.entrySet()) { + put(entry.getKey(), (V) entry.getValue()); } } } @@ -252,9 +253,10 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap { * * @return a collection view of the values contained in this map */ - public Collection values() { - Collection vs = values; - return (vs != null ? vs : (values = new Values())); + @SuppressWarnings("unchecked") + public Collection<Object> values() { + Collection<V> vs = values; + return (Collection<Object>) (vs != null ? vs : (values = new Values())); } /** @@ -264,7 +266,7 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap { * @return true if the map contains the value */ public boolean containsValue(Object key, Object value) { - Collection coll = getCollection(key); + Collection<V> coll = getCollection(key); if (coll == null) { return false; } @@ -278,8 +280,9 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap { * @param key the key to retrieve * @return the collection mapped to the key, null if no mapping */ - public Collection getCollection(Object key) { - return (Collection) decorated().get(key); + @SuppressWarnings("unchecked") + public Collection<V> getCollection(Object key) { + return (Collection<V>) decorated().get(key); } /** @@ -289,7 +292,7 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap { * @return the size of the collection at the key, zero if key not in map */ public int size(Object key) { - Collection coll = getCollection(key); + Collection<V> coll = getCollection(key); if (coll == null) { return 0; } @@ -304,12 +307,12 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap { * @param values the values to add to the collection at the key, null ignored * @return true if this map changed */ - public boolean putAll(Object key, Collection values) { + public boolean putAll(K key, Collection<V> values) { if (values == null || values.size() == 0) { return false; } boolean result = false; - Collection coll = getCollection(key); + Collection<V> coll = getCollection(key); if (coll == null) { coll = createCollection(values.size()); // might produce a non-empty collection coll.addAll(values); @@ -330,12 +333,11 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap { * @param key the key to get an iterator for * @return the iterator of the collection at the key, empty iterator if key not in map */ - public Iterator iterator(Object key) { + public Iterator<V> iterator(Object key) { if (!containsKey(key)) { - return EmptyIterator.INSTANCE; - } else { - return new ValuesIterator(key); + return EmptyIterator.<V>getInstance(); } + return new ValuesIterator(key); } /** @@ -345,10 +347,8 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap { */ public int totalSize() { int total = 0; - Collection values = decorated().values(); - for (Iterator it = values.iterator(); it.hasNext();) { - Collection coll = (Collection) it.next(); - total += coll.size(); + for (Object v : decorated().values()) { + total += CollectionUtils.size(v); } return total; } @@ -363,18 +363,18 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap { * @param size the collection size that is about to be added * @return the new collection */ - protected Collection createCollection(int size) { - return (Collection) collectionFactory.create(); + protected Collection<V> createCollection(int size) { + return collectionFactory.create(); } //----------------------------------------------------------------------- /** * Inner class that provides the values view. */ - private class Values extends AbstractCollection { - public Iterator iterator() { - final IteratorChain chain = new IteratorChain(); - for (Iterator it = keySet().iterator(); it.hasNext();) { + private class Values extends AbstractCollection<V> { + public Iterator<V> iterator() { + final IteratorChain<V> chain = new IteratorChain<V>(); + for (Iterator<K> it = keySet().iterator(); it.hasNext();) { chain.addIterator(new ValuesIterator(it.next())); } return chain; @@ -392,10 +392,10 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap { /** * Inner class that provides the values iterator. */ - private class ValuesIterator implements Iterator { + private class ValuesIterator implements Iterator<V> { private final Object key; - private final Collection values; - private final Iterator iterator; + private final Collection<V> values; + private final Iterator<V> iterator; public ValuesIterator(Object key) { this.key = key; @@ -414,7 +414,7 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap { return iterator.hasNext(); } - public Object next() { + public V next() { return iterator.next(); } } @@ -422,14 +422,14 @@ public class MultiValueMap extends AbstractMapDecorator implements MultiMap { /** * Inner class that provides a simple reflection factory. */ - private static class ReflectionFactory implements Factory { - private final Class clazz; + private static class ReflectionFactory<T extends Collection<?>> implements Factory<T> { + private final Class<T> clazz; - public ReflectionFactory(Class clazz) { + public ReflectionFactory(Class<T> clazz) { this.clazz = clazz; } - public Object create() { + public T create() { try { return clazz.newInstance(); } catch (Exception ex) { http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/PredicatedMap.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/commons/collections/map/PredicatedMap.java b/src/java/org/apache/commons/collections/map/PredicatedMap.java index b334157..537fe35 100644 --- a/src/java/org/apache/commons/collections/map/PredicatedMap.java +++ b/src/java/org/apache/commons/collections/map/PredicatedMap.java @@ -50,17 +50,18 @@ import org.apache.commons.collections.Predicate; * @author Stephen Colebourne * @author Paul Jack */ -public class PredicatedMap - extends AbstractInputCheckedMapDecorator +public class PredicatedMap<K, V> + extends AbstractInputCheckedMapDecorator<K, V> implements Serializable { /** Serialization version */ private static final long serialVersionUID = 7412622456128415156L; /** The key predicate to use */ - protected final Predicate keyPredicate; + protected final Predicate<? super K> keyPredicate; + /** The value predicate to use */ - protected final Predicate valuePredicate; + protected final Predicate<? super V> valuePredicate; /** * Factory method to create a predicated (validating) map. @@ -73,8 +74,8 @@ public class PredicatedMap * @param valuePredicate the predicate to validate to values, null means no check * @throws IllegalArgumentException if the map is null */ - public static Map decorate(Map map, Predicate keyPredicate, Predicate valuePredicate) { - return new PredicatedMap(map, keyPredicate, valuePredicate); + public static <K, V> Map<K, V> decorate(Map<K, V> map, Predicate<? super K> keyPredicate, Predicate<? super V> valuePredicate) { + return new PredicatedMap<K, V>(map, keyPredicate, valuePredicate); } //----------------------------------------------------------------------- @@ -86,17 +87,15 @@ public class PredicatedMap * @param valuePredicate the predicate to validate to values, null means no check * @throws IllegalArgumentException if the map is null */ - protected PredicatedMap(Map map, Predicate keyPredicate, Predicate valuePredicate) { + protected PredicatedMap(Map<K, V> map, Predicate<? super K> keyPredicate, Predicate<? super V> valuePredicate) { super(map); this.keyPredicate = keyPredicate; this.valuePredicate = valuePredicate; - Iterator it = map.entrySet().iterator(); + Iterator<Map.Entry<K, V>> it = map.entrySet().iterator(); while (it.hasNext()) { - Map.Entry entry = (Map.Entry) it.next(); - Object key = entry.getKey(); - Object value = entry.getValue(); - validate(key, value); + Map.Entry<K, V> entry = it.next(); + validate(entry.getKey(), entry.getValue()); } } @@ -121,6 +120,7 @@ public class PredicatedMap * @throws ClassNotFoundException * @since Commons Collections 3.1 */ + @SuppressWarnings("unchecked") private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); map = (Map) in.readObject(); @@ -134,7 +134,7 @@ public class PredicatedMap * @param value the value to validate * @throws IllegalArgumentException if invalid */ - protected void validate(Object key, Object value) { + protected void validate(K key, V value) { if (keyPredicate != null && keyPredicate.evaluate(key) == false) { throw new IllegalArgumentException("Cannot add key - Predicate rejected it"); } @@ -150,7 +150,7 @@ public class PredicatedMap * @throws IllegalArgumentException if invalid * @since Commons Collections 3.1 */ - protected Object checkSetValue(Object value) { + protected V checkSetValue(V value) { if (valuePredicate.evaluate(value) == false) { throw new IllegalArgumentException("Cannot set value - Predicate rejected it"); } @@ -168,20 +168,16 @@ public class PredicatedMap } //----------------------------------------------------------------------- - public Object put(Object key, Object value) { + public V put(K key, V value) { validate(key, value); return map.put(key, value); } - public void putAll(Map mapToCopy) { - Iterator it = mapToCopy.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = (Map.Entry) it.next(); - Object key = entry.getKey(); - Object value = entry.getValue(); - validate(key, value); + public void putAll(Map<? extends K, ? extends V> mapToCopy) { + for (Map.Entry<? extends K, ? extends V> entry : mapToCopy.entrySet()) { + validate(entry.getKey(), entry.getValue()); } - map.putAll(mapToCopy); + super.putAll(mapToCopy); } } http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/PredicatedSortedMap.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/commons/collections/map/PredicatedSortedMap.java b/src/java/org/apache/commons/collections/map/PredicatedSortedMap.java index d1b39e3..63f75a3 100644 --- a/src/java/org/apache/commons/collections/map/PredicatedSortedMap.java +++ b/src/java/org/apache/commons/collections/map/PredicatedSortedMap.java @@ -46,9 +46,7 @@ import org.apache.commons.collections.Predicate; * @author Stephen Colebourne * @author Paul Jack */ -public class PredicatedSortedMap - extends PredicatedMap - implements SortedMap { +public class PredicatedSortedMap<K, V> extends PredicatedMap<K, V> implements SortedMap<K, V> { /** Serialization version */ private static final long serialVersionUID = 3359846175935304332L; @@ -64,8 +62,9 @@ public class PredicatedSortedMap * @param valuePredicate the predicate to validate to values, null means no check * @throws IllegalArgumentException if the map is null */ - public static SortedMap decorate(SortedMap map, Predicate keyPredicate, Predicate valuePredicate) { - return new PredicatedSortedMap(map, keyPredicate, valuePredicate); + public static <K, V> SortedMap<K, V> decorate(SortedMap<K, V> map, + Predicate<? super K> keyPredicate, Predicate<? super V> valuePredicate) { + return new PredicatedSortedMap<K, V>(map, keyPredicate, valuePredicate); } //----------------------------------------------------------------------- @@ -77,7 +76,8 @@ public class PredicatedSortedMap * @param valuePredicate the predicate to validate to values, null means no check * @throws IllegalArgumentException if the map is null */ - protected PredicatedSortedMap(SortedMap map, Predicate keyPredicate, Predicate valuePredicate) { + protected PredicatedSortedMap(SortedMap<K, V> map, Predicate<? super K> keyPredicate, + Predicate<? super V> valuePredicate) { super(map, keyPredicate, valuePredicate); } @@ -87,36 +87,36 @@ public class PredicatedSortedMap * * @return the decorated map */ - protected SortedMap getSortedMap() { - return (SortedMap) map; + protected SortedMap<K, V> getSortedMap() { + return (SortedMap<K, V>) map; } //----------------------------------------------------------------------- - public Object firstKey() { + public K firstKey() { return getSortedMap().firstKey(); } - public Object lastKey() { + public K lastKey() { return getSortedMap().lastKey(); } - public Comparator comparator() { + public Comparator<? super K> comparator() { return getSortedMap().comparator(); } - public SortedMap subMap(Object fromKey, Object toKey) { - SortedMap map = getSortedMap().subMap(fromKey, toKey); - return new PredicatedSortedMap(map, keyPredicate, valuePredicate); + public SortedMap<K, V> subMap(K fromKey, K toKey) { + SortedMap<K, V> map = getSortedMap().subMap(fromKey, toKey); + return new PredicatedSortedMap<K, V>(map, keyPredicate, valuePredicate); } - public SortedMap headMap(Object toKey) { - SortedMap map = getSortedMap().headMap(toKey); - return new PredicatedSortedMap(map, keyPredicate, valuePredicate); + public SortedMap<K, V> headMap(K toKey) { + SortedMap<K, V> map = getSortedMap().headMap(toKey); + return new PredicatedSortedMap<K, V>(map, keyPredicate, valuePredicate); } - public SortedMap tailMap(Object fromKey) { - SortedMap map = getSortedMap().tailMap(fromKey); - return new PredicatedSortedMap(map, keyPredicate, valuePredicate); + public SortedMap<K, V> tailMap(K fromKey) { + SortedMap<K, V> map = getSortedMap().tailMap(fromKey); + return new PredicatedSortedMap<K, V>(map, keyPredicate, valuePredicate); } } http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/ReferenceIdentityMap.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/commons/collections/map/ReferenceIdentityMap.java b/src/java/org/apache/commons/collections/map/ReferenceIdentityMap.java index 39fba2b..7a6ac47 100644 --- a/src/java/org/apache/commons/collections/map/ReferenceIdentityMap.java +++ b/src/java/org/apache/commons/collections/map/ReferenceIdentityMap.java @@ -70,7 +70,7 @@ import java.lang.ref.Reference; * * @author Stephen Colebourne */ -public class ReferenceIdentityMap extends AbstractReferenceMap implements Serializable { +public class ReferenceIdentityMap<K, V> extends AbstractReferenceMap<K, V> implements Serializable { /** Serialization version */ private static final long serialVersionUID = -1266190134568365852L; @@ -80,7 +80,8 @@ public class ReferenceIdentityMap extends AbstractReferenceMap implements Serial * use hard references to keys and soft references to values. */ public ReferenceIdentityMap() { - super(HARD, SOFT, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, false); + super(ReferenceStrength.HARD, ReferenceStrength.SOFT, DEFAULT_CAPACITY, + DEFAULT_LOAD_FACTOR, false); } /** @@ -92,7 +93,7 @@ public class ReferenceIdentityMap extends AbstractReferenceMap implements Serial * @param valueType the type of reference to use for values; * must be {@link #HARD}, {@link #SOFT}, {@link #WEAK} */ - public ReferenceIdentityMap(int keyType, int valueType) { + public ReferenceIdentityMap(ReferenceStrength keyType, ReferenceStrength valueType) { super(keyType, valueType, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, false); } @@ -107,7 +108,8 @@ public class ReferenceIdentityMap extends AbstractReferenceMap implements Serial * @param purgeValues should the value be automatically purged when the * key is garbage collected */ - public ReferenceIdentityMap(int keyType, int valueType, boolean purgeValues) { + public ReferenceIdentityMap(ReferenceStrength keyType, ReferenceStrength valueType, + boolean purgeValues) { super(keyType, valueType, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, purgeValues); } @@ -122,7 +124,8 @@ public class ReferenceIdentityMap extends AbstractReferenceMap implements Serial * @param capacity the initial capacity for the map * @param loadFactor the load factor for the map */ - public ReferenceIdentityMap(int keyType, int valueType, int capacity, float loadFactor) { + public ReferenceIdentityMap(ReferenceStrength keyType, ReferenceStrength valueType, + int capacity, float loadFactor) { super(keyType, valueType, capacity, loadFactor, false); } @@ -139,8 +142,8 @@ public class ReferenceIdentityMap extends AbstractReferenceMap implements Serial * @param purgeValues should the value be automatically purged when the * key is garbage collected */ - public ReferenceIdentityMap(int keyType, int valueType, int capacity, - float loadFactor, boolean purgeValues) { + public ReferenceIdentityMap(ReferenceStrength keyType, ReferenceStrength valueType, + int capacity, float loadFactor, boolean purgeValues) { super(keyType, valueType, capacity, loadFactor, purgeValues); } @@ -182,8 +185,8 @@ public class ReferenceIdentityMap extends AbstractReferenceMap implements Serial * @return true if equal by identity */ protected boolean isEqualKey(Object key1, Object key2) { - key2 = (keyType > HARD ? ((Reference) key2).get() : key2); - return (key1 == key2); + key2 = keyType == ReferenceStrength.HARD ? key2 : ((Reference<?>) key2).get(); + return key1 == key2; } /** @@ -196,7 +199,7 @@ public class ReferenceIdentityMap extends AbstractReferenceMap implements Serial * @return true if equal by identity */ protected boolean isEqualValue(Object value1, Object value2) { - return (value1 == value2); + return value1 == value2; } //----------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/ReferenceMap.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/commons/collections/map/ReferenceMap.java b/src/java/org/apache/commons/collections/map/ReferenceMap.java index 5685711..861db7f 100644 --- a/src/java/org/apache/commons/collections/map/ReferenceMap.java +++ b/src/java/org/apache/commons/collections/map/ReferenceMap.java @@ -73,7 +73,7 @@ import java.io.Serializable; * @author Paul Jack * @author Stephen Colebourne */ -public class ReferenceMap extends AbstractReferenceMap implements Serializable { +public class ReferenceMap<K, V> extends AbstractReferenceMap<K, V> implements Serializable { /** Serialization version */ private static final long serialVersionUID = 1555089888138299607L; @@ -83,7 +83,8 @@ public class ReferenceMap extends AbstractReferenceMap implements Serializable { * use hard references to keys and soft references to values. */ public ReferenceMap() { - super(HARD, SOFT, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, false); + super(ReferenceStrength.HARD, ReferenceStrength.SOFT, DEFAULT_CAPACITY, + DEFAULT_LOAD_FACTOR, false); } /** @@ -95,7 +96,7 @@ public class ReferenceMap extends AbstractReferenceMap implements Serializable { * @param valueType the type of reference to use for values; * must be {@link #HARD}, {@link #SOFT}, {@link #WEAK} */ - public ReferenceMap(int keyType, int valueType) { + public ReferenceMap(ReferenceStrength keyType, ReferenceStrength valueType) { super(keyType, valueType, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, false); } @@ -110,7 +111,7 @@ public class ReferenceMap extends AbstractReferenceMap implements Serializable { * @param purgeValues should the value be automatically purged when the * key is garbage collected */ - public ReferenceMap(int keyType, int valueType, boolean purgeValues) { + public ReferenceMap(ReferenceStrength keyType, ReferenceStrength valueType, boolean purgeValues) { super(keyType, valueType, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, purgeValues); } @@ -126,7 +127,8 @@ public class ReferenceMap extends AbstractReferenceMap implements Serializable { * @param capacity the initial capacity for the map * @param loadFactor the load factor for the map */ - public ReferenceMap(int keyType, int valueType, int capacity, float loadFactor) { + public ReferenceMap(ReferenceStrength keyType, ReferenceStrength valueType, int capacity, + float loadFactor) { super(keyType, valueType, capacity, loadFactor, false); } @@ -144,8 +146,8 @@ public class ReferenceMap extends AbstractReferenceMap implements Serializable { * @param purgeValues should the value be automatically purged when the * key is garbage collected */ - public ReferenceMap(int keyType, int valueType, int capacity, - float loadFactor, boolean purgeValues) { + public ReferenceMap(ReferenceStrength keyType, ReferenceStrength valueType, int capacity, + float loadFactor, boolean purgeValues) { super(keyType, valueType, capacity, loadFactor, purgeValues); }