http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/AbstractInputCheckedMapDecorator.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/commons/collections/map/AbstractInputCheckedMapDecorator.java b/src/java/org/apache/commons/collections/map/AbstractInputCheckedMapDecorator.java index 0add873..e8be0cd 100644 --- a/src/java/org/apache/commons/collections/map/AbstractInputCheckedMapDecorator.java +++ b/src/java/org/apache/commons/collections/map/AbstractInputCheckedMapDecorator.java @@ -44,8 +44,8 @@ import org.apache.commons.collections.set.AbstractSetDecorator; * * @author Stephen Colebourne */ -abstract class AbstractInputCheckedMapDecorator - extends AbstractMapDecorator { +abstract class AbstractInputCheckedMapDecorator<K, V> + extends AbstractMapDecorator<K, V> { /** * Constructor only used in deserialization, do not use otherwise. @@ -60,7 +60,7 @@ abstract class AbstractInputCheckedMapDecorator * @param map the map to decorate, must not be null * @throws IllegalArgumentException if map is null */ - protected AbstractInputCheckedMapDecorator(Map map) { + protected AbstractInputCheckedMapDecorator(Map<K, V> map) { super(map); } @@ -79,7 +79,7 @@ abstract class AbstractInputCheckedMapDecorator * @throws ClassCastException if the class of the specified value is invalid * @throws NullPointerException if the specified value is null and nulls are invalid */ - protected abstract Object checkSetValue(Object value); + protected abstract V checkSetValue(V value); /** * Hook method called to determine if <code>checkSetValue</code> has any effect. @@ -96,41 +96,43 @@ abstract class AbstractInputCheckedMapDecorator } //----------------------------------------------------------------------- - public Set entrySet() { + public Set<Map.Entry<K, V>> entrySet() { if (isSetValueChecking()) { return new EntrySet(map.entrySet(), this); - } else { - return map.entrySet(); } + return map.entrySet(); } //----------------------------------------------------------------------- /** * Implementation of an entry set that checks additions via setValue. */ - static class EntrySet extends AbstractSetDecorator { + @SuppressWarnings("serial") + private class EntrySet extends AbstractSetDecorator<Map.Entry<K, V>> { /** The parent map */ - private final AbstractInputCheckedMapDecorator parent; + private final AbstractInputCheckedMapDecorator<K, V> parent; - protected EntrySet(Set set, AbstractInputCheckedMapDecorator parent) { + protected EntrySet(Set<Map.Entry<K, V>> set, AbstractInputCheckedMapDecorator<K, V> parent) { super(set); this.parent = parent; } - public Iterator iterator() { + public Iterator<Map.Entry<K, V>> iterator() { return new EntrySetIterator(collection.iterator(), parent); } + @SuppressWarnings("unchecked") public Object[] toArray() { Object[] array = collection.toArray(); for (int i = 0; i < array.length; i++) { - array[i] = new MapEntry((Map.Entry) array[i], parent); + array[i] = new MapEntry((Map.Entry<K, V>) array[i], parent); } return array; } - public Object[] toArray(Object array[]) { + @SuppressWarnings("unchecked") + public <T> T[] toArray(T[] array) { Object[] result = array; if (array.length > 0) { // we must create a new array to handle multi-threaded situations @@ -139,12 +141,12 @@ abstract class AbstractInputCheckedMapDecorator } result = collection.toArray(result); for (int i = 0; i < result.length; i++) { - result[i] = new MapEntry((Map.Entry) result[i], parent); + result[i] = new MapEntry((Map.Entry<K, V>) result[i], parent); } // check to see if result should be returned straight if (result.length > array.length) { - return result; + return (T[]) result; } // copy back into input array to fulfil the method contract @@ -159,18 +161,18 @@ abstract class AbstractInputCheckedMapDecorator /** * Implementation of an entry set iterator that checks additions via setValue. */ - static class EntrySetIterator extends AbstractIteratorDecorator { - + private class EntrySetIterator extends AbstractIteratorDecorator<Map.Entry<K, V>> { + /** The parent map */ - private final AbstractInputCheckedMapDecorator parent; - - protected EntrySetIterator(Iterator iterator, AbstractInputCheckedMapDecorator parent) { + private final AbstractInputCheckedMapDecorator<K, V> parent; + + protected EntrySetIterator(Iterator<Map.Entry<K, V>> iterator, AbstractInputCheckedMapDecorator<K, V> parent) { super(iterator); this.parent = parent; } - - public Object next() { - Map.Entry entry = (Map.Entry) iterator.next(); + + public Map.Entry<K, V> next() { + Map.Entry<K, V> entry = iterator.next(); return new MapEntry(entry, parent); } } @@ -178,17 +180,17 @@ abstract class AbstractInputCheckedMapDecorator /** * Implementation of a map entry that checks additions via setValue. */ - static class MapEntry extends AbstractMapEntryDecorator { + private class MapEntry extends AbstractMapEntryDecorator<K, V> { /** The parent map */ - private final AbstractInputCheckedMapDecorator parent; + private final AbstractInputCheckedMapDecorator<K, V> parent; - protected MapEntry(Map.Entry entry, AbstractInputCheckedMapDecorator parent) { + protected MapEntry(Map.Entry<K, V> entry, AbstractInputCheckedMapDecorator<K, V> parent) { super(entry); this.parent = parent; } - public Object setValue(Object value) { + public V setValue(V value) { value = parent.checkSetValue(value); return entry.setValue(value); }
http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/AbstractLinkedMap.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/commons/collections/map/AbstractLinkedMap.java b/src/java/org/apache/commons/collections/map/AbstractLinkedMap.java index 4a735a5..9086918 100644 --- a/src/java/org/apache/commons/collections/map/AbstractLinkedMap.java +++ b/src/java/org/apache/commons/collections/map/AbstractLinkedMap.java @@ -21,7 +21,6 @@ import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; -import org.apache.commons.collections.MapIterator; import org.apache.commons.collections.OrderedIterator; import org.apache.commons.collections.OrderedMap; import org.apache.commons.collections.OrderedMapIterator; @@ -63,10 +62,10 @@ import org.apache.commons.collections.iterators.EmptyOrderedMapIterator; * @author java util LinkedHashMap * @author Stephen Colebourne */ -public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap { +public abstract class AbstractLinkedMap<K, V> extends AbstractHashedMap<K, V> implements OrderedMap<K, V> { /** Header in the linked list */ - protected transient LinkEntry header; + protected transient LinkEntry<K, V> header; /** * Constructor only used in deserialization, do not use otherwise. @@ -115,7 +114,7 @@ public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap { * @param map the map to copy * @throws NullPointerException if the map is null */ - protected AbstractLinkedMap(Map map) { + protected AbstractLinkedMap(Map<K, V> map) { super(map); } @@ -127,7 +126,7 @@ public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap { * the map entry object. */ protected void init() { - header = (LinkEntry) createEntry(null, -1, null, null); + header = createEntry(null, -1, null, null); header.before = header.after = header; } @@ -141,13 +140,13 @@ public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap { public boolean containsValue(Object value) { // override uses faster iterator if (value == null) { - for (LinkEntry entry = header.after; entry != header; entry = entry.after) { + for (LinkEntry<K, V> entry = header.after; entry != header; entry = entry.after) { if (entry.getValue() == null) { return true; } } } else { - for (LinkEntry entry = header.after; entry != header; entry = entry.after) { + for (LinkEntry<K, V> entry = header.after; entry != header; entry = entry.after) { if (isEqualValue(value, entry.getValue())) { return true; } @@ -172,7 +171,7 @@ public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap { * * @return the most recently inserted key */ - public Object firstKey() { + public K firstKey() { if (size == 0) { throw new NoSuchElementException("Map is empty"); } @@ -184,7 +183,7 @@ public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap { * * @return the eldest key */ - public Object lastKey() { + public K lastKey() { if (size == 0) { throw new NoSuchElementException("Map is empty"); } @@ -197,19 +196,23 @@ public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap { * @param key the key to get after * @return the next key */ - public Object nextKey(Object key) { - LinkEntry entry = (LinkEntry) getEntry(key); + public K nextKey(Object key) { + LinkEntry<K, V> entry = getEntry(key); return (entry == null || entry.after == header ? null : entry.after.getKey()); } + protected LinkEntry<K, V> getEntry(Object key) { + return (LinkEntry<K, V>) super.getEntry(key); + } + /** * Gets the previous key in sequence. * * @param key the key to get before * @return the previous key */ - public Object previousKey(Object key) { - LinkEntry entry = (LinkEntry) getEntry(key); + public K previousKey(Object key) { + LinkEntry<K, V> entry = getEntry(key); return (entry == null || entry.before == header ? null : entry.before.getKey()); } @@ -221,14 +224,14 @@ public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap { * @return the key at the specified index * @throws IndexOutOfBoundsException if the index is invalid */ - protected LinkEntry getEntry(int index) { + protected LinkEntry<K, V> getEntry(int index) { if (index < 0) { throw new IndexOutOfBoundsException("Index " + index + " is less than zero"); } if (index >= size) { throw new IndexOutOfBoundsException("Index " + index + " is invalid for size " + size); } - LinkEntry entry; + LinkEntry<K, V> entry; if (index < (size / 2)) { // Search forwards entry = header.after; @@ -251,18 +254,18 @@ public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap { * This implementation adds the entry to the data storage table and * to the end of the linked list. * - * @param entry the entry to add + * @param link the entry to add * @param hashIndex the index into the data array to store at */ - protected void addEntry(HashEntry entry, int hashIndex) { - LinkEntry link = (LinkEntry) entry; + protected void addEntry(HashEntry<K, V> entry, int hashIndex) { + LinkEntry<K, V> link = (LinkEntry<K, V>) entry; link.after = header; link.before = header.before; header.before.after = link; header.before = link; - data[hashIndex] = entry; + data[hashIndex] = link; } - + /** * Creates an entry to store the data. * <p> @@ -274,10 +277,10 @@ public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap { * @param value the value to store * @return the newly created entry */ - protected HashEntry createEntry(HashEntry next, int hashCode, Object key, Object value) { - return new LinkEntry(next, hashCode, key, value); + protected LinkEntry<K, V> createEntry(HashEntry<K, V> next, int hashCode, K key, V value) { + return new LinkEntry<K, V>(next, hashCode, convertKey(key), value); } - + /** * Removes an entry from the map and the linked list. * <p> @@ -288,15 +291,15 @@ public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap { * @param hashIndex the index into the data structure * @param previous the previous entry in the chain */ - protected void removeEntry(HashEntry entry, int hashIndex, HashEntry previous) { - LinkEntry link = (LinkEntry) entry; + protected void removeEntry(HashEntry<K, V> entry, int hashIndex, HashEntry<K, V> previous) { + LinkEntry<K, V> link = (LinkEntry<K, V>) entry; link.before.after = link.after; link.after.before = link.before; link.after = null; link.before = null; super.removeEntry(entry, hashIndex, previous); } - + //----------------------------------------------------------------------- /** * Gets the <code>before</code> field from a <code>LinkEntry</code>. @@ -307,10 +310,10 @@ public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap { * @throws NullPointerException if the entry is null * @since Commons Collections 3.1 */ - protected LinkEntry entryBefore(LinkEntry entry) { + protected LinkEntry<K, V> entryBefore(LinkEntry<K, V> entry) { return entry.before; } - + /** * Gets the <code>after</code> field from a <code>LinkEntry</code>. * Used in subclasses that have no visibility of the field. @@ -320,87 +323,64 @@ public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap { * @throws NullPointerException if the entry is null * @since Commons Collections 3.1 */ - protected LinkEntry entryAfter(LinkEntry entry) { + protected LinkEntry<K, V> entryAfter(LinkEntry<K, V> entry) { return entry.after; } - - //----------------------------------------------------------------------- - /** - * Gets an iterator over the map. - * Changes made to the iterator affect this map. - * <p> - * A MapIterator returns the keys in the map. It also provides convenient - * methods to get the key and value, and set the value. - * It avoids the need to create an entrySet/keySet/values object. - * - * @return the map iterator - */ - public MapIterator mapIterator() { - if (size == 0) { - return EmptyOrderedMapIterator.INSTANCE; - } - return new LinkMapIterator(this); - } + //----------------------------------------------------------------------- /** - * Gets a bidirectional iterator over the map. - * Changes made to the iterator affect this map. - * <p> - * A MapIterator returns the keys in the map. It also provides convenient - * methods to get the key and value, and set the value. - * It avoids the need to create an entrySet/keySet/values object. - * - * @return the map iterator + * {@inheritDoc} */ - public OrderedMapIterator orderedMapIterator() { + public OrderedMapIterator<K, V> mapIterator() { if (size == 0) { - return EmptyOrderedMapIterator.INSTANCE; + return EmptyOrderedMapIterator.<K, V>getInstance(); } - return new LinkMapIterator(this); + return new LinkMapIterator<K, V>(this); } /** * MapIterator implementation. */ - protected static class LinkMapIterator extends LinkIterator implements OrderedMapIterator { - - protected LinkMapIterator(AbstractLinkedMap parent) { + protected static class LinkMapIterator<K, V> extends LinkIterator<K, V> implements + OrderedMapIterator<K, V>, ResettableIterator<K> { + + protected LinkMapIterator(AbstractLinkedMap<K, V> parent) { super(parent); } - public Object next() { + public K next() { return super.nextEntry().getKey(); } - public Object previous() { + public K previous() { return super.previousEntry().getKey(); } - public Object getKey() { - HashEntry current = currentEntry(); + public K getKey() { + LinkEntry<K, V> current = currentEntry(); if (current == null) { throw new IllegalStateException(AbstractHashedMap.GETKEY_INVALID); } return current.getKey(); } - public Object getValue() { - HashEntry current = currentEntry(); + public V getValue() { + LinkEntry<K, V> current = currentEntry(); if (current == null) { throw new IllegalStateException(AbstractHashedMap.GETVALUE_INVALID); } return current.getValue(); } - public Object setValue(Object value) { - HashEntry current = currentEntry(); + public V setValue(V value) { + LinkEntry<K, V> current = currentEntry(); if (current == null) { throw new IllegalStateException(AbstractHashedMap.SETVALUE_INVALID); } return current.setValue(value); } } - + //----------------------------------------------------------------------- /** * Creates an entry set iterator. @@ -408,27 +388,28 @@ public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap { * * @return the entrySet iterator */ - protected Iterator createEntrySetIterator() { + protected Iterator<Map.Entry<K, V>> createEntrySetIterator() { if (size() == 0) { - return EmptyOrderedIterator.INSTANCE; + return EmptyOrderedIterator.<Map.Entry<K, V>>getInstance(); } - return new EntrySetIterator(this); + return new EntrySetIterator<K, V>(this); } /** * EntrySet iterator. */ - protected static class EntrySetIterator extends LinkIterator { - - protected EntrySetIterator(AbstractLinkedMap parent) { + protected static class EntrySetIterator<K, V> extends LinkIterator<K, V> implements + OrderedIterator<Map.Entry<K, V>>, ResettableIterator<Map.Entry<K, V>> { + + protected EntrySetIterator(AbstractLinkedMap<K, V> parent) { super(parent); } - public Object next() { + public Map.Entry<K, V> next() { return super.nextEntry(); } - public Object previous() { + public Map.Entry<K, V> previous() { return super.previousEntry(); } } @@ -440,31 +421,33 @@ public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap { * * @return the keySet iterator */ - protected Iterator createKeySetIterator() { + protected Iterator<K> createKeySetIterator() { if (size() == 0) { - return EmptyOrderedIterator.INSTANCE; + return EmptyOrderedIterator.<K>getInstance(); } - return new KeySetIterator(this); + return new KeySetIterator<K>(this); } /** * KeySet iterator. */ - protected static class KeySetIterator extends EntrySetIterator { + protected static class KeySetIterator<K> extends LinkIterator<K, Object> implements + OrderedIterator<K>, ResettableIterator<K> { - protected KeySetIterator(AbstractLinkedMap parent) { - super(parent); + @SuppressWarnings("unchecked") + protected KeySetIterator(AbstractLinkedMap<K, ?> parent) { + super((AbstractLinkedMap<K, Object>) parent); } - public Object next() { + public K next() { return super.nextEntry().getKey(); } - public Object previous() { + public K previous() { return super.previousEntry().getKey(); } } - + //----------------------------------------------------------------------- /** * Creates a values iterator. @@ -472,31 +455,33 @@ public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap { * * @return the values iterator */ - protected Iterator createValuesIterator() { + protected Iterator<V> createValuesIterator() { if (size() == 0) { - return EmptyOrderedIterator.INSTANCE; + return EmptyOrderedIterator.<V>getInstance(); } - return new ValuesIterator(this); + return new ValuesIterator<V>(this); } /** * Values iterator. */ - protected static class ValuesIterator extends LinkIterator { - - protected ValuesIterator(AbstractLinkedMap parent) { - super(parent); + protected static class ValuesIterator<V> extends LinkIterator<Object, V> implements + OrderedIterator<V>, ResettableIterator<V> { + + @SuppressWarnings("unchecked") + protected ValuesIterator(AbstractLinkedMap<?, V> parent) { + super((AbstractLinkedMap<Object, V>) parent); } - public Object next() { + public V next() { return super.nextEntry().getValue(); } - public Object previous() { + public V previous() { return super.previousEntry().getValue(); } } - + //----------------------------------------------------------------------- /** * LinkEntry that stores the data. @@ -506,12 +491,12 @@ public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap { * The <code>entryXxx()</code> methods on <code>AbstractLinkedMap</code> exist * to provide the necessary access. */ - protected static class LinkEntry extends HashEntry { + protected static class LinkEntry<K, V> extends HashEntry<K, V> { /** The entry before this one in the order */ - protected LinkEntry before; + protected LinkEntry<K, V> before; /** The entry after this one in the order */ - protected LinkEntry after; - + protected LinkEntry<K, V> after; + /** * Constructs a new entry. * @@ -520,27 +505,26 @@ public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap { * @param key the key * @param value the value */ - protected LinkEntry(HashEntry next, int hashCode, Object key, Object value) { + protected LinkEntry(HashEntry<K, V> next, int hashCode, Object key, V value) { super(next, hashCode, key, value); } } - + /** * Base Iterator that iterates in link order. */ - protected static abstract class LinkIterator - implements OrderedIterator, ResettableIterator { - + protected static abstract class LinkIterator<K, V> { + /** The parent map */ - protected final AbstractLinkedMap parent; + protected final AbstractLinkedMap<K, V> parent; /** The current (last returned) entry */ - protected LinkEntry last; + protected LinkEntry<K, V> last; /** The next entry */ - protected LinkEntry next; + protected LinkEntry<K, V> next; /** The modification count expected */ protected int expectedModCount; - - protected LinkIterator(AbstractLinkedMap parent) { + + protected LinkIterator(AbstractLinkedMap<K, V> parent) { super(); this.parent = parent; this.next = parent.header.after; @@ -550,12 +534,12 @@ public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap { public boolean hasNext() { return (next != parent.header); } - + public boolean hasPrevious() { return (next.before != parent.header); } - protected LinkEntry nextEntry() { + protected LinkEntry<K, V> nextEntry() { if (parent.modCount != expectedModCount) { throw new ConcurrentModificationException(); } @@ -567,11 +551,11 @@ public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap { return last; } - protected LinkEntry previousEntry() { + protected LinkEntry<K, V> previousEntry() { if (parent.modCount != expectedModCount) { throw new ConcurrentModificationException(); } - LinkEntry previous = next.before; + LinkEntry<K, V> previous = next.before; if (previous == parent.header) { throw new NoSuchElementException(AbstractHashedMap.NO_PREVIOUS_ENTRY); } @@ -579,11 +563,11 @@ public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap { last = previous; return last; } - - protected LinkEntry currentEntry() { + + protected LinkEntry<K, V> currentEntry() { return last; } - + public void remove() { if (last == null) { throw new IllegalStateException(AbstractHashedMap.REMOVE_INVALID); @@ -595,7 +579,7 @@ public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap { last = null; expectedModCount = parent.modCount; } - + public void reset() { last = null; next = parent.header.after; @@ -604,10 +588,9 @@ public class AbstractLinkedMap extends AbstractHashedMap implements OrderedMap { public String toString() { if (last != null) { return "Iterator[" + last.getKey() + "=" + last.getValue() + "]"; - } else { - return "Iterator[]"; } + return "Iterator[]"; } } - + } http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/AbstractOrderedMapDecorator.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/commons/collections/map/AbstractOrderedMapDecorator.java b/src/java/org/apache/commons/collections/map/AbstractOrderedMapDecorator.java index 4a26fa4..4998a03 100644 --- a/src/java/org/apache/commons/collections/map/AbstractOrderedMapDecorator.java +++ b/src/java/org/apache/commons/collections/map/AbstractOrderedMapDecorator.java @@ -16,7 +16,6 @@ */ package org.apache.commons.collections.map; -import org.apache.commons.collections.MapIterator; import org.apache.commons.collections.OrderedMap; import org.apache.commons.collections.OrderedMapIterator; @@ -37,9 +36,8 @@ import org.apache.commons.collections.OrderedMapIterator; * * @author Stephen Colebourne */ -public abstract class AbstractOrderedMapDecorator - extends AbstractMapDecorator - implements OrderedMap { +public abstract class AbstractOrderedMapDecorator<K, V> extends AbstractMapDecorator<K, V> + implements OrderedMap<K, V> { /** * Constructor only used in deserialization, do not use otherwise. @@ -55,7 +53,7 @@ public abstract class AbstractOrderedMapDecorator * @param map the map to decorate, must not be null * @throws IllegalArgumentException if the collection is null */ - public AbstractOrderedMapDecorator(OrderedMap map) { + public AbstractOrderedMapDecorator(OrderedMap<K, V> map) { super(map); } @@ -64,33 +62,29 @@ public abstract class AbstractOrderedMapDecorator * * @return the decorated map */ - protected OrderedMap decorated() { - return (OrderedMap) super.decorated(); + protected OrderedMap<K, V> decorated() { + return (OrderedMap<K, V>) super.decorated(); } //----------------------------------------------------------------------- - public Object firstKey() { + public K firstKey() { return decorated().firstKey(); } - public Object lastKey() { + public K lastKey() { return decorated().lastKey(); } - public Object nextKey(Object key) { + public K nextKey(K key) { return decorated().nextKey(key); } - public Object previousKey(Object key) { + public K previousKey(K key) { return decorated().previousKey(key); } - public MapIterator mapIterator() { + public OrderedMapIterator<K, V> mapIterator() { return decorated().mapIterator(); } - public OrderedMapIterator orderedMapIterator() { - return decorated().orderedMapIterator(); - } - } http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/AbstractReferenceMap.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/commons/collections/map/AbstractReferenceMap.java b/src/java/org/apache/commons/collections/map/AbstractReferenceMap.java index f5b31a2..60a0699 100644 --- a/src/java/org/apache/commons/collections/map/AbstractReferenceMap.java +++ b/src/java/org/apache/commons/collections/map/AbstractReferenceMap.java @@ -5,9 +5,9 @@ * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -72,38 +72,61 @@ import org.apache.commons.collections.keyvalue.DefaultMapEntry; * <code>ResettableIterator</code> and calling <code>reset()</code>. * <p> * This implementation is not synchronized. - * You can use {@link java.util.Collections#synchronizedMap} to + * You can use {@link java.util.Collections#synchronizedMap} to * provide synchronized access to a <code>ReferenceMap</code>. * * @see java.lang.ref.Reference * @since Commons Collections 3.1 (extracted from ReferenceMap in 3.0) * @version $Revision$ $Date$ - * + * * @author Paul Jack * @author Stephen Colebourne */ -public abstract class AbstractReferenceMap extends AbstractHashedMap { +public abstract class AbstractReferenceMap<K, V> extends AbstractHashedMap<K, V> { + + /** + * Reference type enum. + */ + public static enum ReferenceStrength { + HARD(0), SOFT(1), WEAK(2); + + /** value */ + public final int value; - /** Constant indicating that hard references should be used */ - public static final int HARD = 0; + /** + * Resolve enum from int. + * @param value + * @return ReferenceType + * @throws IllegalArgumentException if the specified value is invalid. + */ + public static ReferenceStrength resolve(int value) { + switch (value) { + case 0: + return HARD; + case 1: + return SOFT; + case 2: + return WEAK; + default: + throw new IllegalArgumentException(); + } + } - /** Constant indicating that soft references should be used */ - public static final int SOFT = 1; + private ReferenceStrength(int value) { + this.value = value; + } - /** Constant indicating that weak references should be used */ - public static final int WEAK = 2; + } /** - * The reference type for keys. Must be HARD, SOFT, WEAK. - * @serial + * The reference type for keys. */ - protected int keyType; + protected ReferenceStrength keyType; /** - * The reference type for values. Must be HARD, SOFT, WEAK. - * @serial + * The reference type for values. */ - protected int valueType; + protected ReferenceStrength valueType; /** * Should the value be automatically purged when the associated key has been collected? @@ -114,7 +137,7 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { * ReferenceQueue used to eliminate stale mappings. * See purge. */ - private transient ReferenceQueue queue; + private transient ReferenceQueue<Object> queue; //----------------------------------------------------------------------- /** @@ -134,15 +157,13 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { * must be {@link #HARD}, {@link #SOFT}, {@link #WEAK} * @param capacity the initial capacity for the map * @param loadFactor the load factor for the map - * @param purgeValues should the value be automatically purged when the - * key is garbage collected + * @param purgeValues should the value be automatically purged when the + * key is garbage collected */ protected AbstractReferenceMap( - int keyType, int valueType, int capacity, + ReferenceStrength keyType, ReferenceStrength valueType, int capacity, float loadFactor, boolean purgeValues) { super(capacity, loadFactor); - verify("keyType", keyType); - verify("valueType", valueType); this.keyType = keyType; this.valueType = valueType; this.purgeValues = purgeValues; @@ -152,27 +173,13 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { * Initialise this subclass during construction, cloning or deserialization. */ protected void init() { - queue = new ReferenceQueue(); - } - - //----------------------------------------------------------------------- - /** - * Checks the type int is a valid value. - * - * @param name the name for error messages - * @param type the type value to check - * @throws IllegalArgumentException if the value if invalid - */ - private static void verify(String name, int type) { - if ((type < HARD) || (type > WEAK)) { - throw new IllegalArgumentException(name + " must be HARD, SOFT, WEAK."); - } + queue = new ReferenceQueue<Object>(); } //----------------------------------------------------------------------- /** * Gets the size of the map. - * + * * @return the size */ public int size() { @@ -182,7 +189,7 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { /** * Checks whether the map is currently empty. - * + * * @return true if the map is currently size zero */ public boolean isEmpty() { @@ -192,13 +199,13 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { /** * Checks whether the map contains the specified key. - * + * * @param key the key to search for * @return true if the map contains the key */ public boolean containsKey(Object key) { purgeBeforeRead(); - Entry entry = getEntry(key); + Entry<K, V> entry = getEntry(key); if (entry == null) { return false; } @@ -207,7 +214,7 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { /** * Checks whether the map contains the specified value. - * + * * @param value the value to search for * @return true if the map contains the value */ @@ -221,13 +228,13 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { /** * Gets the value mapped to the key specified. - * + * * @param key the key * @return the mapped value, null if no match */ - public Object get(Object key) { + public V get(Object key) { purgeBeforeRead(); - Entry entry = getEntry(key); + Entry<K, V> entry = getEntry(key); if (entry == null) { return null; } @@ -238,13 +245,13 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { /** * Puts a key-value mapping into this map. * Neither the key nor the value may be null. - * + * * @param key the key to add, must not be null * @param value the value to add, must not be null * @return the value previously mapped to this key, null if none * @throws NullPointerException if either the key or value is null */ - public Object put(Object key, Object value) { + public V put(K key, V value) { if (key == null) { throw new NullPointerException("null keys not allowed"); } @@ -255,14 +262,14 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { purgeBeforeWrite(); return super.put(key, value); } - + /** * Removes the specified mapping from this map. - * + * * @param key the mapping to remove * @return the value mapped to the removed key, null if key not in map */ - public Object remove(Object key) { + public V remove(Object key) { if (key == null) { return null; } @@ -282,11 +289,11 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { /** * Gets a MapIterator over the reference map. * The iterator only returns valid key/value pairs. - * + * * @return a map iterator */ - public MapIterator mapIterator() { - return new ReferenceMapIterator(this); + public MapIterator<K, V> mapIterator() { + return new ReferenceMapIterator<K, V>(this); } /** @@ -296,9 +303,9 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { * * @return a set view of this map's entries */ - public Set entrySet() { + public Set<Map.Entry<K, V>> entrySet() { if (entrySet == null) { - entrySet = new ReferenceEntrySet(this); + entrySet = new ReferenceEntrySet<K, V>(this); } return entrySet; } @@ -308,9 +315,9 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { * * @return a set view of this map's keys */ - public Set keySet() { + public Set<K> keySet() { if (keySet == null) { - keySet = new ReferenceKeySet(this); + keySet = new ReferenceKeySet<K>(this); } return keySet; } @@ -320,9 +327,9 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { * * @return a set view of this map's values */ - public Collection values() { + public Collection<V> values() { if (values == null) { - values = new ReferenceValues(this); + values = new ReferenceValues<V>(this); } return values; } @@ -355,7 +362,7 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { * background thread. */ protected void purge() { - Reference ref = queue.poll(); + Reference<?> ref = queue.poll(); while (ref != null) { purge(ref); ref = queue.poll(); @@ -364,19 +371,19 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { /** * Purges the specified reference. - * + * * @param ref the reference to purge */ - protected void purge(Reference ref) { + protected void purge(Reference<?> ref) { // The hashCode of the reference is the hashCode of the - // mapping key, even if the reference refers to the + // mapping key, even if the reference refers to the // mapping value... int hash = ref.hashCode(); int index = hashIndex(hash, data.length); - HashEntry previous = null; - HashEntry entry = data[index]; + HashEntry<K, V> previous = null; + HashEntry<K, V> entry = data[index]; while (entry != null) { - if (((ReferenceEntry) entry).purge(ref)) { + if (((ReferenceEntry<K, V>) entry).purge(ref)) { if (previous == null) { data[index] = entry.next; } else { @@ -394,93 +401,93 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { //----------------------------------------------------------------------- /** * Gets the entry mapped to the key specified. - * + * * @param key the key * @return the entry, null if no match */ - protected HashEntry getEntry(Object key) { + protected HashEntry<K, V> getEntry(Object key) { if (key == null) { return null; - } else { - return super.getEntry(key); } + return super.getEntry(key); } /** * Gets the hash code for a MapEntry. * Subclasses can override this, for example to use the identityHashCode. - * + * * @param key the key to get a hash code for, may be null * @param value the value to get a hash code for, may be null * @return the hash code, as per the MapEntry specification */ protected int hashEntry(Object key, Object value) { return (key == null ? 0 : key.hashCode()) ^ - (value == null ? 0 : value.hashCode()); + (value == null ? 0 : value.hashCode()); } - + /** * Compares two keys, in internal converted form, to see if they are equal. * <p> * This implementation converts the key from the entry to a real reference * before comparison. - * + * * @param key1 the first key to compare passed in from outside * @param key2 the second key extracted from the entry via <code>entry.key</code> * @return true if equal */ + @SuppressWarnings("unchecked") protected boolean isEqualKey(Object key1, Object key2) { - key2 = (keyType > HARD ? ((Reference) key2).get() : key2); + key2 = (keyType == ReferenceStrength.HARD ? key2 : ((Reference<K>) key2).get()); return (key1 == key2 || key1.equals(key2)); } - + /** * Creates a ReferenceEntry instead of a HashEntry. - * + * * @param next the next entry in sequence * @param hashCode the hash code to use * @param key the key to store * @param value the value to store * @return the newly created entry */ - protected HashEntry createEntry(HashEntry next, int hashCode, Object key, Object value) { - return new ReferenceEntry(this, next, hashCode, key, value); + protected ReferenceEntry<K, V> createEntry(HashEntry<K, V> next, int hashCode, K key, V value) { + return new ReferenceEntry<K, V>(this, next, hashCode, key, value); } /** * Creates an entry set iterator. - * + * * @return the entrySet iterator */ - protected Iterator createEntrySetIterator() { - return new ReferenceEntrySetIterator(this); + protected Iterator<Map.Entry<K, V>> createEntrySetIterator() { + return new ReferenceEntrySetIterator<K, V>(this); } /** * Creates an key set iterator. - * + * * @return the keySet iterator */ - protected Iterator createKeySetIterator() { - return new ReferenceKeySetIterator(this); + protected Iterator<K> createKeySetIterator() { + return new ReferenceKeySetIterator<K>(this); } /** * Creates an values iterator. - * + * * @return the values iterator */ - protected Iterator createValuesIterator() { - return new ReferenceValuesIterator(this); + protected Iterator<V> createValuesIterator() { + return new ReferenceValuesIterator<V>(this); } //----------------------------------------------------------------------- /** * EntrySet implementation. */ - static class ReferenceEntrySet extends EntrySet { - - protected ReferenceEntrySet(AbstractHashedMap parent) { + static class ReferenceEntrySet<K, V> extends EntrySet<K, V> { + + protected ReferenceEntrySet(AbstractHashedMap<K, V> parent) { super(parent); } @@ -488,13 +495,11 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { return toArray(new Object[0]); } - public Object[] toArray(Object[] arr) { + public <T> T[] toArray(T[] arr) { // special implementation to handle disappearing entries - ArrayList list = new ArrayList(); - Iterator iterator = iterator(); - while (iterator.hasNext()) { - Entry e = (Entry) iterator.next(); - list.add(new DefaultMapEntry(e.getKey(), e.getValue())); + ArrayList<Map.Entry<K, V>> list = new ArrayList<Map.Entry<K, V>>(); + for (Map.Entry<K, V> entry : this) { + list.add(new DefaultMapEntry<K, V>(entry)); } return list.toArray(arr); } @@ -504,9 +509,9 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { /** * KeySet implementation. */ - static class ReferenceKeySet extends KeySet { - - protected ReferenceKeySet(AbstractHashedMap parent) { + static class ReferenceKeySet<K> extends KeySet<K> { + + protected ReferenceKeySet(AbstractHashedMap<K, ?> parent) { super(parent); } @@ -514,11 +519,11 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { return toArray(new Object[0]); } - public Object[] toArray(Object[] arr) { + public <T> T[] toArray(T[] arr) { // special implementation to handle disappearing keys - List list = new ArrayList(parent.size()); - for (Iterator it = iterator(); it.hasNext(); ) { - list.add(it.next()); + List<K> list = new ArrayList<K>(parent.size()); + for (K key : this) { + list.add(key); } return list.toArray(arr); } @@ -528,9 +533,9 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { /** * Values implementation. */ - static class ReferenceValues extends Values { - - protected ReferenceValues(AbstractHashedMap parent) { + static class ReferenceValues<V> extends Values<V> { + + protected ReferenceValues(AbstractHashedMap<?, V> parent) { super(parent); } @@ -538,11 +543,11 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { return toArray(new Object[0]); } - public Object[] toArray(Object[] arr) { + public <T> T[] toArray(T[] arr) { // special implementation to handle disappearing values - List list = new ArrayList(parent.size()); - for (Iterator it = iterator(); it.hasNext(); ) { - list.add(it.next()); + List<V> list = new ArrayList<V>(parent.size()); + for (V value : this) { + list.add(value); } return list.toArray(arr); } @@ -554,23 +559,23 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { * <p> * If getKey() or getValue() returns null, it means * the mapping is stale and should be removed. - * + * * @since Commons Collections 3.1 */ - protected static class ReferenceEntry extends HashEntry { + protected static class ReferenceEntry<K, V> extends HashEntry<K, V> { /** The parent map */ - protected final AbstractReferenceMap parent; + protected final AbstractReferenceMap<K, V> parent; /** * Creates a new entry object for the ReferenceMap. - * + * * @param parent the parent map * @param next the next entry in the hash bucket * @param hashCode the hash code of the key * @param key the key * @param value the value */ - public ReferenceEntry(AbstractReferenceMap parent, HashEntry next, int hashCode, Object key, Object value) { + public ReferenceEntry(AbstractReferenceMap<K, V> parent, HashEntry<K, V> next, int hashCode, K key, V value) { super(next, hashCode, null, null); this.parent = parent; this.key = toReference(parent.keyType, key, hashCode); @@ -580,33 +585,36 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { /** * Gets the key from the entry. * This method dereferences weak and soft keys and thus may return null. - * + * * @return the key, which may be null if it was garbage collected */ - public Object getKey() { - return (parent.keyType > HARD) ? ((Reference) key).get() : key; + @SuppressWarnings("unchecked") + public K getKey() { + return (K) ((parent.keyType == ReferenceStrength.HARD) ? key : ((Reference<K>) key).get()); } /** * Gets the value from the entry. * This method dereferences weak and soft value and thus may return null. - * + * * @return the value, which may be null if it was garbage collected */ - public Object getValue() { - return (parent.valueType > HARD) ? ((Reference) value).get() : value; + @SuppressWarnings("unchecked") + public V getValue() { + return (V) ((parent.valueType == ReferenceStrength.HARD) ? value : ((Reference<V>) value).get()); } /** * Sets the value of the entry. - * + * * @param obj the object to store * @return the previous value */ - public Object setValue(Object obj) { - Object old = getValue(); - if (parent.valueType > HARD) { - ((Reference)value).clear(); + @SuppressWarnings("unchecked") + public V setValue(V obj) { + V old = getValue(); + if (parent.valueType != ReferenceStrength.HARD) { + ((Reference<V>) value).clear(); } value = toReference(parent.valueType, obj, hashCode); return old; @@ -617,10 +625,11 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { * <p> * This implementation uses <code>isEqualKey</code> and * <code>isEqualValue</code> on the main map for comparison. - * + * * @param obj the other map entry to compare to * @return true if equal, false if not */ + @SuppressWarnings("unchecked") public boolean equals(Object obj) { if (obj == this) { return true; @@ -628,7 +637,7 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { if (obj instanceof Map.Entry == false) { return false; } - + Map.Entry entry = (Map.Entry)obj; Object entryKey = entry.getKey(); // convert to hard reference Object entryValue = entry.getValue(); // convert to hard reference @@ -645,7 +654,7 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { * Gets the hashcode of the entry using temporary hard references. * <p> * This implementation uses <code>hashEntry</code> on the main map. - * + * * @return the hashcode of the entry */ public int hashCode() { @@ -662,13 +671,17 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { * this number might be different from referent.hashCode() if * the referent represents a value and not a key */ - protected Object toReference(int type, Object referent, int hash) { - switch (type) { - case HARD: return referent; - case SOFT: return new SoftRef(hash, referent, parent.queue); - case WEAK: return new WeakRef(hash, referent, parent.queue); - default: throw new Error(); + protected <T> Object toReference(ReferenceStrength type, T referent, int hash) { + if (type == ReferenceStrength.HARD) { + return referent; } + if (type == ReferenceStrength.SOFT) { + return new SoftRef<T>(hash, referent, parent.queue); + } + if (type == ReferenceStrength.WEAK) { + return new WeakRef<T>(hash, referent, parent.queue); + } + throw new Error(); } /** @@ -676,15 +689,15 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { * @param ref the reference to purge * @return true or false */ - boolean purge(Reference ref) { - boolean r = (parent.keyType > HARD) && (key == ref); - r = r || ((parent.valueType > HARD) && (value == ref)); + boolean purge(Reference<?> ref) { + boolean r = (parent.keyType != ReferenceStrength.HARD) && (key == ref); + r = r || ((parent.valueType != ReferenceStrength.HARD) && (value == ref)); if (r) { - if (parent.keyType > HARD) { - ((Reference)key).clear(); + if (parent.keyType != ReferenceStrength.HARD) { + ((Reference<?>) key).clear(); } - if (parent.valueType > HARD) { - ((Reference)value).clear(); + if (parent.valueType != ReferenceStrength.HARD) { + ((Reference<?>) value).clear(); } else if (parent.purgeValues) { value = null; } @@ -694,36 +707,36 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { /** * Gets the next entry in the bucket. - * + * * @return the next entry in the bucket */ - protected ReferenceEntry next() { - return (ReferenceEntry) next; + protected ReferenceEntry<K, V> next() { + return (ReferenceEntry<K, V>) next; } } //----------------------------------------------------------------------- /** - * The EntrySet iterator. + * Base iterator class. */ - static class ReferenceEntrySetIterator implements Iterator { + static class ReferenceBaseIterator<K, V> { /** The parent map */ - final AbstractReferenceMap parent; - + final AbstractReferenceMap<K, V> parent; + // These fields keep track of where we are in the table. int index; - ReferenceEntry entry; - ReferenceEntry previous; + ReferenceEntry<K, V> entry; + ReferenceEntry<K, V> previous; // These Object fields provide hard references to the // current and next entry; this assures that if hasNext() // returns true, next() will actually return a valid element. - Object nextKey, nextValue; - Object currentKey, currentValue; + K currentKey, nextKey; + V currentValue, nextValue; int expectedModCount; - public ReferenceEntrySetIterator(AbstractReferenceMap parent) { + public ReferenceBaseIterator(AbstractReferenceMap<K, V> parent) { super(); this.parent = parent; index = (parent.size() != 0 ? parent.data.length : 0); @@ -735,11 +748,11 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { public boolean hasNext() { checkMod(); while (nextNull()) { - ReferenceEntry e = entry; + ReferenceEntry<K, V> e = entry; int i = index; while ((e == null) && (i > 0)) { i--; - e = (ReferenceEntry) parent.data[i]; + e = (ReferenceEntry<K, V>) parent.data[i]; } entry = e; index = i; @@ -767,7 +780,7 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { return (nextKey == null) || (nextValue == null); } - protected ReferenceEntry nextEntry() { + protected ReferenceEntry<K, V> nextEntry() { checkMod(); if (nextNull() && !hasNext()) { throw new NoSuchElementException(); @@ -781,14 +794,10 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { return previous; } - protected ReferenceEntry currentEntry() { + protected ReferenceEntry<K, V> currentEntry() { checkMod(); return previous; } - - public Object next() { - return nextEntry(); - } public void remove() { checkMod(); @@ -804,15 +813,31 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { } /** - * The keySet iterator. + * The EntrySet iterator. */ - static class ReferenceKeySetIterator extends ReferenceEntrySetIterator { - - ReferenceKeySetIterator(AbstractReferenceMap parent) { + static class ReferenceEntrySetIterator<K, V> extends ReferenceBaseIterator<K, V> implements Iterator<Map.Entry<K, V>> { + + public ReferenceEntrySetIterator(AbstractReferenceMap<K, V> parent) { super(parent); } - - public Object next() { + + public Map.Entry<K, V> next() { + return nextEntry(); + } + + } + + /** + * The keySet iterator. + */ + static class ReferenceKeySetIterator<K> extends ReferenceBaseIterator<K, Object> implements Iterator<K> { + + @SuppressWarnings("unchecked") + ReferenceKeySetIterator(AbstractReferenceMap<K, ?> parent) { + super((AbstractReferenceMap<K, Object>) parent); + } + + public K next() { return nextEntry().getKey(); } } @@ -820,13 +845,14 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { /** * The values iterator. */ - static class ReferenceValuesIterator extends ReferenceEntrySetIterator { - - ReferenceValuesIterator(AbstractReferenceMap parent) { - super(parent); + static class ReferenceValuesIterator<V> extends ReferenceBaseIterator<Object, V> implements Iterator<V> { + + @SuppressWarnings("unchecked") + ReferenceValuesIterator(AbstractReferenceMap<?, V> parent) { + super((AbstractReferenceMap<Object, V>) parent); } - - public Object next() { + + public V next() { return nextEntry().getValue(); } } @@ -834,41 +860,41 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { /** * The MapIterator implementation. */ - static class ReferenceMapIterator extends ReferenceEntrySetIterator implements MapIterator { - - protected ReferenceMapIterator(AbstractReferenceMap parent) { + static class ReferenceMapIterator<K, V> extends ReferenceBaseIterator<K, V> implements MapIterator<K, V> { + + protected ReferenceMapIterator(AbstractReferenceMap<K, V> parent) { super(parent); } - public Object next() { + public K next() { return nextEntry().getKey(); } - public Object getKey() { - HashEntry current = currentEntry(); + public K getKey() { + HashEntry<K, V> current = currentEntry(); if (current == null) { throw new IllegalStateException(AbstractHashedMap.GETKEY_INVALID); } return current.getKey(); } - public Object getValue() { - HashEntry current = currentEntry(); + public V getValue() { + HashEntry<K, V> current = currentEntry(); if (current == null) { throw new IllegalStateException(AbstractHashedMap.GETVALUE_INVALID); } return current.getValue(); } - public Object setValue(Object value) { - HashEntry current = currentEntry(); + public V setValue(V value) { + HashEntry<K, V> current = currentEntry(); if (current == null) { throw new IllegalStateException(AbstractHashedMap.SETVALUE_INVALID); } return current.setValue(value); } } - + //----------------------------------------------------------------------- // These two classes store the hashCode of the key of // of the mapping, so that after they're dequeued a quick @@ -877,11 +903,11 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { /** * A soft reference holder. */ - static class SoftRef extends SoftReference { + static class SoftRef<T> extends SoftReference<T> { /** the hashCode of the key (even if the reference points to a value) */ private int hash; - public SoftRef(int hash, Object r, ReferenceQueue q) { + public SoftRef(int hash, T r, ReferenceQueue<? super T> q) { super(r, q); this.hash = hash; } @@ -894,11 +920,11 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { /** * A weak reference holder. */ - static class WeakRef extends WeakReference { + static class WeakRef<T> extends WeakReference<T> { /** the hashCode of the key (even if the reference points to a value) */ private int hash; - public WeakRef(int hash, Object r, ReferenceQueue q) { + public WeakRef(int hash, T r, ReferenceQueue<? super T> q) { super(r, q); this.hash = hash; } @@ -924,16 +950,16 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { * Subclasses may override if they have a specific field that must be present * on read before this implementation will work. Generally, the read determines * what must be serialized here, if anything. - * + * * @param out the output stream */ protected void doWriteObject(ObjectOutputStream out) throws IOException { - out.writeInt(keyType); - out.writeInt(valueType); + out.writeInt(keyType.value); + out.writeInt(valueType.value); out.writeBoolean(purgeValues); out.writeFloat(loadFactor); out.writeInt(data.length); - for (MapIterator it = mapIterator(); it.hasNext();) { + for (MapIterator<K, V> it = mapIterator(); it.hasNext();) { out.writeObject(it.next()); out.writeObject(it.getValue()); } @@ -955,23 +981,24 @@ public abstract class AbstractReferenceMap extends AbstractHashedMap { * <p> * Subclasses may override if the subclass has a specific field that must be present * before <code>put()</code> or <code>calculateThreshold()</code> will work correctly. - * + * * @param in the input stream */ + @SuppressWarnings("unchecked") protected void doReadObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - this.keyType = in.readInt(); - this.valueType = in.readInt(); + this.keyType = ReferenceStrength.resolve(in.readInt()); + this.valueType = ReferenceStrength.resolve(in.readInt()); this.purgeValues = in.readBoolean(); this.loadFactor = in.readFloat(); int capacity = in.readInt(); init(); data = new HashEntry[capacity]; while (true) { - Object key = in.readObject(); + K key = (K) in.readObject(); if (key == null) { break; } - Object value = in.readObject(); + V value = (V) in.readObject(); put(key, value); } threshold = calculateThreshold(data.length, loadFactor); http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/AbstractSortedMapDecorator.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/commons/collections/map/AbstractSortedMapDecorator.java b/src/java/org/apache/commons/collections/map/AbstractSortedMapDecorator.java index eae1600..7c9a35b 100644 --- a/src/java/org/apache/commons/collections/map/AbstractSortedMapDecorator.java +++ b/src/java/org/apache/commons/collections/map/AbstractSortedMapDecorator.java @@ -38,9 +38,8 @@ import java.util.SortedMap; * * @author Stephen Colebourne */ -public abstract class AbstractSortedMapDecorator<K, V> - extends AbstractMapDecorator<K, V> - implements SortedMap<K, V> { +public abstract class AbstractSortedMapDecorator<K, V> extends AbstractMapDecorator<K, V> implements + SortedMap<K, V> { /** * Constructor only used in deserialization, do not use otherwise. http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/CaseInsensitiveMap.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/commons/collections/map/CaseInsensitiveMap.java b/src/java/org/apache/commons/collections/map/CaseInsensitiveMap.java index 7d5a18c..05f4206 100644 --- a/src/java/org/apache/commons/collections/map/CaseInsensitiveMap.java +++ b/src/java/org/apache/commons/collections/map/CaseInsensitiveMap.java @@ -57,7 +57,7 @@ import java.util.Map; * * @author Commons-Collections team */ -public class CaseInsensitiveMap extends AbstractHashedMap implements Serializable, Cloneable { +public class CaseInsensitiveMap<K, V> extends AbstractHashedMap<K, V> implements Serializable, Cloneable { /** Serialisation version */ private static final long serialVersionUID = -7074655917369299456L; @@ -102,7 +102,7 @@ public class CaseInsensitiveMap extends AbstractHashedMap implements Serializabl * @param map the map to copy * @throws NullPointerException if the map is null */ - public CaseInsensitiveMap(Map map) { + public CaseInsensitiveMap(Map<K, V> map) { super(map); } @@ -119,9 +119,8 @@ public class CaseInsensitiveMap extends AbstractHashedMap implements Serializabl protected Object convertKey(Object key) { if (key != null) { return key.toString().toLowerCase(); - } else { - return AbstractHashedMap.NULL; } + return AbstractHashedMap.NULL; } //----------------------------------------------------------------------- @@ -130,8 +129,8 @@ public class CaseInsensitiveMap extends AbstractHashedMap implements Serializabl * * @return a shallow clone */ - public Object clone() { - return super.clone(); + public CaseInsensitiveMap<K, V> clone() { + return (CaseInsensitiveMap<K, V>) super.clone(); } /** http://git-wip-us.apache.org/repos/asf/commons-collections/blob/884baf0d/src/java/org/apache/commons/collections/map/CompositeMap.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/commons/collections/map/CompositeMap.java b/src/java/org/apache/commons/collections/map/CompositeMap.java index b806c62..264d7ec 100644 --- a/src/java/org/apache/commons/collections/map/CompositeMap.java +++ b/src/java/org/apache/commons/collections/map/CompositeMap.java @@ -5,9 +5,9 @@ * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,7 +17,6 @@ package org.apache.commons.collections.map; import java.util.Collection; -import java.util.Iterator; import java.util.Map; import java.util.Set; @@ -35,7 +34,7 @@ import org.apache.commons.collections.set.CompositeSet; * <strong>Note that CompositeMap is not synchronized and is not thread-safe.</strong> * If you wish to use this map from multiple threads concurrently, you must use * appropriate synchronization. The simplest approach is to wrap this map - * using {@link java.util.Collections#synchronizedMap(Map)}. This class may throw + * using {@link java.util.Collections#synchronizedMap(Map)}. This class may throw * exceptions when accessed by concurrent threads without synchronization. * * @since Commons Collections 3.0 @@ -43,62 +42,66 @@ import org.apache.commons.collections.set.CompositeSet; * * @author Brian McCallister */ -public class CompositeMap implements Map { +public class CompositeMap<K, V> implements Map<K, V> { /** Array of all maps in the composite */ - private Map[] composite; + private Map<K, V>[] composite; /** Handle mutation operations */ - private MapMutator mutator; + private MapMutator<K, V> mutator; /** * Create a new, empty, CompositeMap. */ + @SuppressWarnings("unchecked") public CompositeMap() { - this(new Map[]{}, null); + this(new Map[] {}, null); } /** * Create a new CompositeMap with two composited Map instances. - * + * * @param one the first Map to be composited * @param two the second Map to be composited * @throws IllegalArgumentException if there is a key collision */ - public CompositeMap(Map one, Map two) { - this(new Map[]{one, two}, null); + @SuppressWarnings("unchecked") + public CompositeMap(Map<K, V> one, Map<K, V> two) { + this(new Map[] { one, two }, null); } /** * Create a new CompositeMap with two composited Map instances. - * + * * @param one the first Map to be composited * @param two the second Map to be composited * @param mutator MapMutator to be used for mutation operations */ - public CompositeMap(Map one, Map two, MapMutator mutator) { - this(new Map[]{one, two}, mutator); + @SuppressWarnings("unchecked") + public CompositeMap(Map<K, V> one, Map<K, V> two, MapMutator<K, V> mutator) { + this(new Map[] { one, two }, mutator); } /** * Create a new CompositeMap which composites all of the Map instances in the * argument. It copies the argument array, it does not use it directly. - * + * * @param composite the Maps to be composited * @throws IllegalArgumentException if there is a key collision */ - public CompositeMap(Map[] composite) { + public CompositeMap(Map<K, V>[] composite) { this(composite, null); } /** * Create a new CompositeMap which composites all of the Map instances in the * argument. It copies the argument array, it does not use it directly. - * + * * @param composite Maps to be composited * @param mutator MapMutator to be used for mutation operations */ - public CompositeMap(Map[] composite, MapMutator mutator) { + @SuppressWarnings("unchecked") + public CompositeMap(Map<K, V>[] composite, MapMutator<K, V> mutator) { this.mutator = mutator; this.composite = new Map[0]; for (int i = composite.length - 1; i >= 0; --i) { @@ -109,13 +112,13 @@ public class CompositeMap implements Map { //----------------------------------------------------------------------- /** * Specify the MapMutator to be used by mutation operations. - * + * * @param mutator the MapMutator to be used for mutation delegation */ - public void setMutator(MapMutator mutator) { + public void setMutator(MapMutator<K, V> mutator) { this.mutator = mutator; } - + /** * Add an additional Map to the composite. * @@ -123,35 +126,35 @@ public class CompositeMap implements Map { * @throws IllegalArgumentException if there is a key collision and there is no * MapMutator set to handle it. */ - public synchronized void addComposited(Map map) throws IllegalArgumentException { + @SuppressWarnings("unchecked") + public synchronized void addComposited(Map<K, V> map) throws IllegalArgumentException { for (int i = composite.length - 1; i >= 0; --i) { - Collection intersect = CollectionUtils.intersection(this.composite[i].keySet(), map.keySet()); + Collection<K> intersect = CollectionUtils.intersection(this.composite[i].keySet(), map.keySet()); if (intersect.size() != 0) { if (this.mutator == null) { throw new IllegalArgumentException("Key collision adding Map to CompositeMap"); } - else { - this.mutator.resolveCollision(this, this.composite[i], map, intersect); - } + this.mutator.resolveCollision(this, this.composite[i], map, intersect); } } - Map[] temp = new Map[this.composite.length + 1]; + Map<K, V>[] temp = new Map[this.composite.length + 1]; System.arraycopy(this.composite, 0, temp, 0, this.composite.length); temp[temp.length - 1] = map; this.composite = temp; } - + /** * Remove a Map from the composite. * * @param map the Map to be removed from the composite * @return The removed Map or <code>null</code> if map is not in the composite */ - public synchronized Map removeComposited(Map map) { + @SuppressWarnings("unchecked") + public synchronized Map<K, V> removeComposited(Map<K, V> map) { int size = this.composite.length; for (int i = 0; i < size; ++i) { if (this.composite[i].equals(map)) { - Map[] temp = new Map[size - 1]; + Map<K, V>[] temp = new Map[size - 1]; System.arraycopy(this.composite, 0, temp, 0, i); System.arraycopy(this.composite, i + 1, temp, i, size - i - 1); this.composite = temp; @@ -161,7 +164,7 @@ public class CompositeMap implements Map { return null; } - //----------------------------------------------------------------------- + //----------------------------------------------------------------------- /** * Calls <code>clear()</code> on all composited Maps. * @@ -172,7 +175,7 @@ public class CompositeMap implements Map { this.composite[i].clear(); } } - + /** * Returns <tt>true</tt> if this map contains a mapping for the specified * key. More formally, returns <tt>true</tt> if and only if @@ -197,7 +200,7 @@ public class CompositeMap implements Map { } return false; } - + /** * Returns <tt>true</tt> if this map maps one or more keys to the * specified value. More formally, returns <tt>true</tt> if and only if @@ -222,7 +225,7 @@ public class CompositeMap implements Map { } return false; } - + /** * Returns a set view of the mappings contained in this map. Each element * in the returned set is a <code>Map.Entry</code>. The set is backed by the @@ -240,14 +243,14 @@ public class CompositeMap implements Map { * @see CompositeSet * @return a set view of the mappings contained in this map. */ - public Set entrySet() { - CompositeSet entries = new CompositeSet(); - for (int i = this.composite.length - 1; i >= 0; --i) { - entries.addComposited(this.composite[i].entrySet()); + public Set<Map.Entry<K, V>> entrySet() { + CompositeSet<Map.Entry<K, V>> entries = new CompositeSet<Map.Entry<K,V>>(); + for (int i = composite.length - 1; i >= 0; --i) { + entries.addComposited((Collection<Map.Entry<K, V>>) composite[i].entrySet()); } return entries; } - + /** * Returns the value to which this map maps the specified key. Returns * <tt>null</tt> if the map contains no mapping for this key. A return @@ -272,7 +275,7 @@ public class CompositeMap implements Map { * * @see #containsKey(Object) */ - public Object get(Object key) { + public V get(Object key) { for (int i = this.composite.length - 1; i >= 0; --i) { if (this.composite[i].containsKey(key)) { return this.composite[i].get(key); @@ -280,7 +283,7 @@ public class CompositeMap implements Map { } return null; } - + /** * Returns <tt>true</tt> if this map contains no key-value mappings. * @@ -294,7 +297,7 @@ public class CompositeMap implements Map { } return true; } - + /** * Returns a set view of the keys contained in this map. The set is * backed by the map, so changes to the map are reflected in the set, and @@ -310,14 +313,14 @@ public class CompositeMap implements Map { * * @return a set view of the keys contained in this map. */ - public Set keySet() { - CompositeSet keys = new CompositeSet(); + public Set<K> keySet() { + CompositeSet<K> keys = new CompositeSet<K>(); for (int i = this.composite.length - 1; i >= 0; --i) { keys.addComposited(this.composite[i].keySet()); } return keys; } - + /** * Associates the specified value with the specified key in this map * (optional operation). If the map previously contained a mapping for @@ -343,13 +346,13 @@ public class CompositeMap implements Map { * keys or values, and the specified key or value is * <tt>null</tt>. */ - public Object put(Object key, Object value) { + public V put(K key, V value) { if (this.mutator == null) { throw new UnsupportedOperationException("No mutator specified"); } return this.mutator.put(this, this.composite, key, value); } - + /** * Copies all of the mappings from the specified map to this map * (optional operation). The effect of this call is equivalent to that @@ -372,13 +375,13 @@ public class CompositeMap implements Map { * this map does not permit <tt>null</tt> keys or values, and the * specified map contains <tt>null</tt> keys or values. */ - public void putAll(Map map) { + public void putAll(Map<? extends K, ? extends V> map) { if (this.mutator == null) { throw new UnsupportedOperationException("No mutator specified"); } this.mutator.putAll(this, this.composite, map); } - + /** * Removes the mapping for this key from this map if it is present * (optional operation). More formally, if this map contains a mapping @@ -404,7 +407,7 @@ public class CompositeMap implements Map { * @throws UnsupportedOperationException if the <tt>remove</tt> method is * not supported by the composited map containing the key */ - public Object remove(Object key) { + public V remove(Object key) { for (int i = this.composite.length - 1; i >= 0; --i) { if (this.composite[i].containsKey(key)) { return this.composite[i].remove(key); @@ -412,7 +415,7 @@ public class CompositeMap implements Map { } return null; } - + /** * Returns the number of key-value mappings in this map. If the * map contains more than <tt>Integer.MAX_VALUE</tt> elements, returns @@ -427,7 +430,7 @@ public class CompositeMap implements Map { } return size; } - + /** * Returns a collection view of the values contained in this map. The * collection is backed by the map, so changes to the map are reflected in @@ -441,20 +444,21 @@ public class CompositeMap implements Map { * * @return a collection view of the values contained in this map. */ - public Collection values() { - CompositeCollection keys = new CompositeCollection(); - for (int i = this.composite.length - 1; i >= 0; --i) { - keys.addComposited(this.composite[i].values()); + public Collection<V> values() { + CompositeCollection<V> values = new CompositeCollection<V>(); + for (int i = composite.length - 1; i >= 0; --i) { + values.addComposited((Collection<V>) composite[i].values()); } - return keys; + return values; } - + /** * Checks if this Map equals another as per the Map specification. - * + * * @param obj the object to compare to * @return true if the maps are equal */ + @SuppressWarnings("unchecked") public boolean equals(Object obj) { if (obj instanceof Map) { Map map = (Map) obj; @@ -462,24 +466,24 @@ public class CompositeMap implements Map { } return false; } - + /** * Gets a hash code for the Map as per the Map specification. */ public int hashCode() { int code = 0; - for (Iterator i = this.entrySet().iterator(); i.hasNext();) { - code += i.next().hashCode(); + for (Map.Entry<K, V> entry : entrySet()) { + code += entry.hashCode(); } return code; } - + /** * This interface allows definition for all of the indeterminate * mutators in a CompositeMap, as well as providing a hook for * callbacks on key collisions. */ - public static interface MapMutator { + public static interface MapMutator<K, V> { /** * Called when adding a new Composited Map results in a * key collision. @@ -490,9 +494,9 @@ public class CompositeMap implements Map { * @param added the Map being added * @param intersect the intersection of the keysets of the existing and added maps */ - public void resolveCollision( - CompositeMap composite, Map existing, Map added, Collection intersect); - + public void resolveCollision(CompositeMap<K, V> composite, Map<K, V> existing, + Map<K, V> added, Collection<K> intersect); + /** * Called when the CompositeMap.put() method is invoked. * @@ -515,8 +519,8 @@ public class CompositeMap implements Map { * keys or values, and the specified key or value is * <tt>null</tt>. */ - public Object put(CompositeMap map, Map[] composited, Object key, Object value); - + public V put(CompositeMap<K, V> map, Map<K, V>[] composited, K key, V value); + /** * Called when the CompositeMap.putAll() method is invoked. * @@ -533,6 +537,7 @@ public class CompositeMap implements Map { * keys or values, and the specified key or value is * <tt>null</tt>. */ - public void putAll(CompositeMap map, Map[] composited, Map mapToAdd); + public void putAll(CompositeMap<K, V> map, Map<K, V>[] composited, + Map<? extends K, ? extends V> mapToAdd); } }
