Merging from -r468106:814127 of collections_jdk5_branch - namely where this code was generified; mostly in r738956.
Also see the following revisions: ------------------------------------------------------------------------ r468690 | scolebourne | 2006-10-28 06:03:11 -0700 (Sat, 28 Oct 2006) | 1 line COLLECTIONS-229 - Remove deprecated classes and code ------------------------------------------------------------------------ git-svn-id: https://svn.apache.org/repos/asf/commons/proper/collections/trunk@815022 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
8bdb561312
commit
2854004d91
|
@ -42,29 +42,37 @@ import org.apache.commons.collections.keyvalue.AbstractMapEntryDecorator;
|
||||||
* @author Matthew Hawthorne
|
* @author Matthew Hawthorne
|
||||||
* @author Stephen Colebourne
|
* @author Stephen Colebourne
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractDualBidiMap implements BidiMap {
|
public abstract class AbstractDualBidiMap<K, V> implements BidiMap<K, V> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delegate map array. The first map contains standard entries, and the
|
* Normal delegate map.
|
||||||
* second contains inverses.
|
|
||||||
*/
|
*/
|
||||||
protected transient final Map[] maps = new Map[2];
|
protected transient Map<K, V> normalMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse delegate map.
|
||||||
|
*/
|
||||||
|
protected transient Map<V, K> reverseMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inverse view of this map.
|
* Inverse view of this map.
|
||||||
*/
|
*/
|
||||||
protected transient BidiMap inverseBidiMap = null;
|
protected transient BidiMap<V, K> inverseBidiMap = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View of the keys.
|
* View of the keys.
|
||||||
*/
|
*/
|
||||||
protected transient Set keySet = null;
|
protected transient Set<K> keySet = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View of the values.
|
* View of the values.
|
||||||
*/
|
*/
|
||||||
protected transient Collection values = null;
|
protected transient Collection<V> values = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View of the entries.
|
* View of the entries.
|
||||||
*/
|
*/
|
||||||
protected transient Set entrySet = null;
|
protected transient Set<Map.Entry<K, V>> entrySet = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an empty map, initialised by <code>createMap</code>.
|
* Creates an empty map, initialised by <code>createMap</code>.
|
||||||
|
@ -75,8 +83,6 @@ public abstract class AbstractDualBidiMap implements BidiMap {
|
||||||
*/
|
*/
|
||||||
protected AbstractDualBidiMap() {
|
protected AbstractDualBidiMap() {
|
||||||
super();
|
super();
|
||||||
maps[0] = createMap();
|
|
||||||
maps[1] = createMap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,18 +94,18 @@ public abstract class AbstractDualBidiMap implements BidiMap {
|
||||||
* Neither map is validated, so nulls may be passed in.
|
* Neither map is validated, so nulls may be passed in.
|
||||||
* If you choose to do this then the subclass constructor must populate
|
* If you choose to do this then the subclass constructor must populate
|
||||||
* the <code>maps[]</code> instance variable itself.
|
* the <code>maps[]</code> instance variable itself.
|
||||||
*
|
*
|
||||||
* @param normalMap the normal direction map
|
* @param normalMap the normal direction map
|
||||||
* @param reverseMap the reverse direction map
|
* @param reverseMap the reverse direction map
|
||||||
* @since Commons Collections 3.1
|
* @since Commons Collections 3.1
|
||||||
*/
|
*/
|
||||||
protected AbstractDualBidiMap(Map normalMap, Map reverseMap) {
|
protected AbstractDualBidiMap(Map<K, V> normalMap, Map<V, K> reverseMap) {
|
||||||
super();
|
super();
|
||||||
maps[0] = normalMap;
|
this.normalMap = normalMap;
|
||||||
maps[1] = reverseMap;
|
this.reverseMap = reverseMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a map that decorates the specified maps,
|
* Constructs a map that decorates the specified maps,
|
||||||
* used by the subclass <code>createBidiMap</code> implementation.
|
* used by the subclass <code>createBidiMap</code> implementation.
|
||||||
*
|
*
|
||||||
|
@ -107,104 +113,89 @@ public abstract class AbstractDualBidiMap implements BidiMap {
|
||||||
* @param reverseMap the reverse direction map
|
* @param reverseMap the reverse direction map
|
||||||
* @param inverseBidiMap the inverse BidiMap
|
* @param inverseBidiMap the inverse BidiMap
|
||||||
*/
|
*/
|
||||||
protected AbstractDualBidiMap(Map normalMap, Map reverseMap, BidiMap inverseBidiMap) {
|
protected AbstractDualBidiMap(Map<K, V> normalMap, Map<V, K> reverseMap, BidiMap<V, K> inverseBidiMap) {
|
||||||
super();
|
super();
|
||||||
maps[0] = normalMap;
|
this.normalMap = normalMap;
|
||||||
maps[1] = reverseMap;
|
this.reverseMap = reverseMap;
|
||||||
this.inverseBidiMap = inverseBidiMap;
|
this.inverseBidiMap = inverseBidiMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new instance of the map used by the subclass to store data.
|
|
||||||
* <p>
|
|
||||||
* This design is deeply flawed and has been deprecated.
|
|
||||||
* It relied on subclass data being used during a superclass constructor.
|
|
||||||
*
|
|
||||||
* @return the map to be used for internal storage
|
|
||||||
* @deprecated For constructors, use the new two map constructor.
|
|
||||||
* For deserialization, populate the maps array directly in readObject.
|
|
||||||
*/
|
|
||||||
protected Map createMap() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of the subclass.
|
* Creates a new instance of the subclass.
|
||||||
*
|
*
|
||||||
* @param normalMap the normal direction map
|
* @param normalMap the normal direction map
|
||||||
* @param reverseMap the reverse direction map
|
* @param reverseMap the reverse direction map
|
||||||
* @param inverseMap this map, which is the inverse in the new map
|
* @param inverseMap this map, which is the inverse in the new map
|
||||||
* @return the inverse map
|
* @return the inverse map
|
||||||
*/
|
*/
|
||||||
protected abstract BidiMap createBidiMap(Map normalMap, Map reverseMap, BidiMap inverseMap);
|
protected abstract BidiMap<V, K> createBidiMap(Map<V, K> normalMap, Map<K, V> reverseMap, BidiMap<K, V> inverseMap);
|
||||||
|
|
||||||
// Map delegation
|
// Map delegation
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
public Object get(Object key) {
|
public V get(Object key) {
|
||||||
return maps[0].get(key);
|
return normalMap.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int size() {
|
public int size() {
|
||||||
return maps[0].size();
|
return normalMap.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return maps[0].isEmpty();
|
return normalMap.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsKey(Object key) {
|
public boolean containsKey(Object key) {
|
||||||
return maps[0].containsKey(key);
|
return normalMap.containsKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
return maps[0].equals(obj);
|
return normalMap.equals(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return maps[0].hashCode();
|
return normalMap.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return maps[0].toString();
|
return normalMap.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// BidiMap changes
|
// BidiMap changes
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
public Object put(Object key, Object value) {
|
public V put(K key, V value) {
|
||||||
if (maps[0].containsKey(key)) {
|
if (normalMap.containsKey(key)) {
|
||||||
maps[1].remove(maps[0].get(key));
|
reverseMap.remove(normalMap.get(key));
|
||||||
}
|
}
|
||||||
if (maps[1].containsKey(value)) {
|
if (reverseMap.containsKey(value)) {
|
||||||
maps[0].remove(maps[1].get(value));
|
normalMap.remove(reverseMap.get(value));
|
||||||
}
|
}
|
||||||
final Object obj = maps[0].put(key, value);
|
final V obj = normalMap.put(key, value);
|
||||||
maps[1].put(value, key);
|
reverseMap.put(value, key);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void putAll(Map map) {
|
public void putAll(Map<? extends K, ? extends V> map) {
|
||||||
for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
|
for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
|
||||||
Map.Entry entry = (Map.Entry) it.next();
|
|
||||||
put(entry.getKey(), entry.getValue());
|
put(entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object remove(Object key) {
|
public V remove(Object key) {
|
||||||
Object value = null;
|
V value = null;
|
||||||
if (maps[0].containsKey(key)) {
|
if (normalMap.containsKey(key)) {
|
||||||
value = maps[0].remove(key);
|
value = normalMap.remove(key);
|
||||||
maps[1].remove(value);
|
reverseMap.remove(value);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
maps[0].clear();
|
normalMap.clear();
|
||||||
maps[1].clear();
|
reverseMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsValue(Object value) {
|
public boolean containsValue(Object value) {
|
||||||
return maps[1].containsKey(value);
|
return reverseMap.containsKey(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// BidiMap
|
// BidiMap
|
||||||
|
@ -217,45 +208,45 @@ public abstract class AbstractDualBidiMap implements BidiMap {
|
||||||
* The setValue() methods only allow a new value to be set.
|
* The setValue() methods only allow a new value to be set.
|
||||||
* If the value being set is already in the map, an IllegalArgumentException
|
* If the value being set is already in the map, an IllegalArgumentException
|
||||||
* is thrown (as setValue cannot change the size of the map).
|
* is thrown (as setValue cannot change the size of the map).
|
||||||
*
|
*
|
||||||
* @return a map iterator
|
* @return a map iterator
|
||||||
*/
|
*/
|
||||||
public MapIterator mapIterator() {
|
public MapIterator<K, V> mapIterator() {
|
||||||
return new BidiMapIterator(this);
|
return new BidiMapIterator<K, V>(this);
|
||||||
}
|
|
||||||
|
|
||||||
public Object getKey(Object value) {
|
|
||||||
return maps[1].get(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object removeValue(Object value) {
|
public K getKey(Object value) {
|
||||||
Object key = null;
|
return reverseMap.get(value);
|
||||||
if (maps[1].containsKey(value)) {
|
}
|
||||||
key = maps[1].remove(value);
|
|
||||||
maps[0].remove(key);
|
public K removeValue(Object value) {
|
||||||
|
K key = null;
|
||||||
|
if (reverseMap.containsKey(value)) {
|
||||||
|
key = reverseMap.remove(value);
|
||||||
|
normalMap.remove(key);
|
||||||
}
|
}
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BidiMap inverseBidiMap() {
|
public BidiMap<V, K> inverseBidiMap() {
|
||||||
if (inverseBidiMap == null) {
|
if (inverseBidiMap == null) {
|
||||||
inverseBidiMap = createBidiMap(maps[1], maps[0], this);
|
inverseBidiMap = createBidiMap(reverseMap, normalMap, this);
|
||||||
}
|
}
|
||||||
return inverseBidiMap;
|
return inverseBidiMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map views
|
// Map views
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
/**
|
/**
|
||||||
* Gets a keySet view of the map.
|
* Gets a keySet view of the map.
|
||||||
* Changes made on the view are reflected in the map.
|
* Changes made on the view are reflected in the map.
|
||||||
* The set supports remove and clear but not add.
|
* The set supports remove and clear but not add.
|
||||||
*
|
*
|
||||||
* @return the keySet view
|
* @return the keySet view
|
||||||
*/
|
*/
|
||||||
public Set keySet() {
|
public Set<K> keySet() {
|
||||||
if (keySet == null) {
|
if (keySet == null) {
|
||||||
keySet = new KeySet(this);
|
keySet = new KeySet<K>(this);
|
||||||
}
|
}
|
||||||
return keySet;
|
return keySet;
|
||||||
}
|
}
|
||||||
|
@ -263,24 +254,24 @@ public abstract class AbstractDualBidiMap implements BidiMap {
|
||||||
/**
|
/**
|
||||||
* Creates a key set iterator.
|
* Creates a key set iterator.
|
||||||
* Subclasses can override this to return iterators with different properties.
|
* Subclasses can override this to return iterators with different properties.
|
||||||
*
|
*
|
||||||
* @param iterator the iterator to decorate
|
* @param iterator the iterator to decorate
|
||||||
* @return the keySet iterator
|
* @return the keySet iterator
|
||||||
*/
|
*/
|
||||||
protected Iterator createKeySetIterator(Iterator iterator) {
|
protected Iterator<K> createKeySetIterator(Iterator<K> iterator) {
|
||||||
return new KeySetIterator(iterator, this);
|
return new KeySetIterator<K>(iterator, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a values view of the map.
|
* Gets a values view of the map.
|
||||||
* Changes made on the view are reflected in the map.
|
* Changes made on the view are reflected in the map.
|
||||||
* The set supports remove and clear but not add.
|
* The set supports remove and clear but not add.
|
||||||
*
|
*
|
||||||
* @return the values view
|
* @return the values view
|
||||||
*/
|
*/
|
||||||
public Collection values() {
|
public Collection<V> values() {
|
||||||
if (values == null) {
|
if (values == null) {
|
||||||
values = new Values(this);
|
values = new Values<V>(this);
|
||||||
}
|
}
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
@ -288,12 +279,12 @@ public abstract class AbstractDualBidiMap implements BidiMap {
|
||||||
/**
|
/**
|
||||||
* Creates a values iterator.
|
* Creates a values iterator.
|
||||||
* Subclasses can override this to return iterators with different properties.
|
* Subclasses can override this to return iterators with different properties.
|
||||||
*
|
*
|
||||||
* @param iterator the iterator to decorate
|
* @param iterator the iterator to decorate
|
||||||
* @return the values iterator
|
* @return the values iterator
|
||||||
*/
|
*/
|
||||||
protected Iterator createValuesIterator(Iterator iterator) {
|
protected Iterator<V> createValuesIterator(Iterator<V> iterator) {
|
||||||
return new ValuesIterator(iterator, this);
|
return new ValuesIterator<V>(iterator, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -304,53 +295,54 @@ public abstract class AbstractDualBidiMap implements BidiMap {
|
||||||
* The Map Entry setValue() method only allow a new value to be set.
|
* The Map Entry setValue() method only allow a new value to be set.
|
||||||
* If the value being set is already in the map, an IllegalArgumentException
|
* If the value being set is already in the map, an IllegalArgumentException
|
||||||
* is thrown (as setValue cannot change the size of the map).
|
* is thrown (as setValue cannot change the size of the map).
|
||||||
*
|
*
|
||||||
* @return the entrySet view
|
* @return the entrySet view
|
||||||
*/
|
*/
|
||||||
public Set entrySet() {
|
public Set<Map.Entry<K, V>> entrySet() {
|
||||||
if (entrySet == null) {
|
if (entrySet == null) {
|
||||||
entrySet = new EntrySet(this);
|
entrySet = new EntrySet<K, V>(this);
|
||||||
}
|
}
|
||||||
return entrySet;
|
return entrySet;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an entry set iterator.
|
* Creates an entry set iterator.
|
||||||
* Subclasses can override this to return iterators with different properties.
|
* Subclasses can override this to return iterators with different properties.
|
||||||
*
|
*
|
||||||
* @param iterator the iterator to decorate
|
* @param iterator the iterator to decorate
|
||||||
* @return the entrySet iterator
|
* @return the entrySet iterator
|
||||||
*/
|
*/
|
||||||
protected Iterator createEntrySetIterator(Iterator iterator) {
|
protected Iterator<Map.Entry<K, V>> createEntrySetIterator(Iterator<Map.Entry<K, V>> iterator) {
|
||||||
return new EntrySetIterator(iterator, this);
|
return new EntrySetIterator<K, V>(iterator, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
/**
|
/**
|
||||||
* Inner class View.
|
* Inner class View.
|
||||||
*/
|
*/
|
||||||
protected static abstract class View extends AbstractCollectionDecorator {
|
@SuppressWarnings("serial")
|
||||||
|
protected static abstract class View<K, V, E> extends AbstractCollectionDecorator<E> {
|
||||||
|
|
||||||
/** The parent map */
|
/** The parent map */
|
||||||
protected final AbstractDualBidiMap parent;
|
protected final AbstractDualBidiMap<K, V> parent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new view of the BidiMap.
|
* Constructs a new view of the BidiMap.
|
||||||
*
|
*
|
||||||
* @param coll the collection view being decorated
|
* @param coll the collection view being decorated
|
||||||
* @param parent the parent BidiMap
|
* @param parent the parent BidiMap
|
||||||
*/
|
*/
|
||||||
protected View(Collection coll, AbstractDualBidiMap parent) {
|
protected View(Collection<E> coll, AbstractDualBidiMap<K, V> parent) {
|
||||||
super(coll);
|
super(coll);
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean removeAll(Collection coll) {
|
public boolean removeAll(Collection<?> coll) {
|
||||||
if (parent.isEmpty() || coll.isEmpty()) {
|
if (parent.isEmpty() || coll.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
boolean modified = false;
|
boolean modified = false;
|
||||||
Iterator it = iterator();
|
Iterator<E> it = iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
if (coll.contains(it.next())) {
|
if (coll.contains(it.next())) {
|
||||||
it.remove();
|
it.remove();
|
||||||
|
@ -360,7 +352,7 @@ public abstract class AbstractDualBidiMap implements BidiMap {
|
||||||
return modified;
|
return modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean retainAll(Collection coll) {
|
public boolean retainAll(Collection<?> coll) {
|
||||||
if (parent.isEmpty()) {
|
if (parent.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -369,7 +361,7 @@ public abstract class AbstractDualBidiMap implements BidiMap {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
boolean modified = false;
|
boolean modified = false;
|
||||||
Iterator it = iterator();
|
Iterator<E> it = iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
if (coll.contains(it.next()) == false) {
|
if (coll.contains(it.next()) == false) {
|
||||||
it.remove();
|
it.remove();
|
||||||
|
@ -378,80 +370,86 @@ public abstract class AbstractDualBidiMap implements BidiMap {
|
||||||
}
|
}
|
||||||
return modified;
|
return modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
parent.clear();
|
parent.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
/**
|
/**
|
||||||
* Inner class KeySet.
|
* Inner class KeySet.
|
||||||
*/
|
*/
|
||||||
protected static class KeySet extends View implements Set {
|
protected static class KeySet<K> extends View<K, Object, K> implements Set<K> {
|
||||||
|
|
||||||
|
/** Serialization version */
|
||||||
|
private static final long serialVersionUID = -7107935777385040694L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new view of the BidiMap.
|
* Constructs a new view of the BidiMap.
|
||||||
*
|
*
|
||||||
* @param parent the parent BidiMap
|
* @param parent the parent BidiMap
|
||||||
*/
|
*/
|
||||||
protected KeySet(AbstractDualBidiMap parent) {
|
@SuppressWarnings("unchecked")
|
||||||
super(parent.maps[0].keySet(), parent);
|
protected KeySet(AbstractDualBidiMap<K, ?> parent) {
|
||||||
|
super(parent.normalMap.keySet(), (AbstractDualBidiMap<K, Object>) parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator iterator() {
|
public Iterator<K> iterator() {
|
||||||
return parent.createKeySetIterator(super.iterator());
|
return parent.createKeySetIterator(super.iterator());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean contains(Object key) {
|
public boolean contains(Object key) {
|
||||||
return parent.maps[0].containsKey(key);
|
return parent.normalMap.containsKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean remove(Object key) {
|
public boolean remove(Object key) {
|
||||||
if (parent.maps[0].containsKey(key)) {
|
if (parent.normalMap.containsKey(key)) {
|
||||||
Object value = parent.maps[0].remove(key);
|
Object value = parent.normalMap.remove(key);
|
||||||
parent.maps[1].remove(value);
|
parent.reverseMap.remove(value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inner class KeySetIterator.
|
* Inner class KeySetIterator.
|
||||||
*/
|
*/
|
||||||
protected static class KeySetIterator extends AbstractIteratorDecorator {
|
protected static class KeySetIterator<K> extends AbstractIteratorDecorator<K> {
|
||||||
|
|
||||||
/** The parent map */
|
/** The parent map */
|
||||||
protected final AbstractDualBidiMap parent;
|
protected final AbstractDualBidiMap<K, ?> parent;
|
||||||
|
|
||||||
/** The last returned key */
|
/** The last returned key */
|
||||||
protected Object lastKey = null;
|
protected K lastKey = null;
|
||||||
|
|
||||||
/** Whether remove is allowed at present */
|
/** Whether remove is allowed at present */
|
||||||
protected boolean canRemove = false;
|
protected boolean canRemove = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
* @param iterator the iterator to decorate
|
* @param iterator the iterator to decorate
|
||||||
* @param parent the parent map
|
* @param parent the parent map
|
||||||
*/
|
*/
|
||||||
protected KeySetIterator(Iterator iterator, AbstractDualBidiMap parent) {
|
protected KeySetIterator(Iterator<K> iterator, AbstractDualBidiMap<K, ?> parent) {
|
||||||
super(iterator);
|
super(iterator);
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object next() {
|
public K next() {
|
||||||
lastKey = super.next();
|
lastKey = super.next();
|
||||||
canRemove = true;
|
canRemove = true;
|
||||||
return lastKey;
|
return lastKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove() {
|
public void remove() {
|
||||||
if (canRemove == false) {
|
if (canRemove == false) {
|
||||||
throw new IllegalStateException("Iterator remove() can only be called once after next()");
|
throw new IllegalStateException("Iterator remove() can only be called once after next()");
|
||||||
}
|
}
|
||||||
Object value = parent.maps[0].get(lastKey);
|
Object value = parent.normalMap.get(lastKey);
|
||||||
super.remove();
|
super.remove();
|
||||||
parent.maps[1].remove(value);
|
parent.reverseMap.remove(value);
|
||||||
lastKey = null;
|
lastKey = null;
|
||||||
canRemove = false;
|
canRemove = false;
|
||||||
}
|
}
|
||||||
|
@ -461,69 +459,76 @@ public abstract class AbstractDualBidiMap implements BidiMap {
|
||||||
/**
|
/**
|
||||||
* Inner class Values.
|
* Inner class Values.
|
||||||
*/
|
*/
|
||||||
protected static class Values extends View implements Set {
|
protected static class Values<V> extends View<Object, V, V> implements Set<V> {
|
||||||
|
|
||||||
|
/** Serialization version */
|
||||||
|
private static final long serialVersionUID = 4023777119829639864L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new view of the BidiMap.
|
* Constructs a new view of the BidiMap.
|
||||||
*
|
*
|
||||||
* @param parent the parent BidiMap
|
* @param parent the parent BidiMap
|
||||||
*/
|
*/
|
||||||
protected Values(AbstractDualBidiMap parent) {
|
@SuppressWarnings("unchecked")
|
||||||
super(parent.maps[0].values(), parent);
|
protected Values(AbstractDualBidiMap<?, V> parent) {
|
||||||
|
super(parent.normalMap.values(), (AbstractDualBidiMap<Object, V>) parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator iterator() {
|
public Iterator<V> iterator() {
|
||||||
return parent.createValuesIterator(super.iterator());
|
return parent.createValuesIterator(super.iterator());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean contains(Object value) {
|
public boolean contains(Object value) {
|
||||||
return parent.maps[1].containsKey(value);
|
return parent.reverseMap.containsKey(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean remove(Object value) {
|
public boolean remove(Object value) {
|
||||||
if (parent.maps[1].containsKey(value)) {
|
if (parent.reverseMap.containsKey(value)) {
|
||||||
Object key = parent.maps[1].remove(value);
|
Object key = parent.reverseMap.remove(value);
|
||||||
parent.maps[0].remove(key);
|
parent.normalMap.remove(key);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inner class ValuesIterator.
|
* Inner class ValuesIterator.
|
||||||
*/
|
*/
|
||||||
protected static class ValuesIterator extends AbstractIteratorDecorator {
|
protected static class ValuesIterator<V> extends AbstractIteratorDecorator<V> {
|
||||||
|
|
||||||
/** The parent map */
|
/** The parent map */
|
||||||
protected final AbstractDualBidiMap parent;
|
protected final AbstractDualBidiMap<Object, V> parent;
|
||||||
|
|
||||||
/** The last returned value */
|
/** The last returned value */
|
||||||
protected Object lastValue = null;
|
protected V lastValue = null;
|
||||||
|
|
||||||
/** Whether remove is allowed at present */
|
/** Whether remove is allowed at present */
|
||||||
protected boolean canRemove = false;
|
protected boolean canRemove = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
* @param iterator the iterator to decorate
|
* @param iterator the iterator to decorate
|
||||||
* @param parent the parent map
|
* @param parent the parent map
|
||||||
*/
|
*/
|
||||||
protected ValuesIterator(Iterator iterator, AbstractDualBidiMap parent) {
|
@SuppressWarnings("unchecked")
|
||||||
|
protected ValuesIterator(Iterator<V> iterator, AbstractDualBidiMap<?, V> parent) {
|
||||||
super(iterator);
|
super(iterator);
|
||||||
this.parent = parent;
|
this.parent = (AbstractDualBidiMap<Object, V>) parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object next() {
|
public V next() {
|
||||||
lastValue = super.next();
|
lastValue = super.next();
|
||||||
canRemove = true;
|
canRemove = true;
|
||||||
return lastValue;
|
return lastValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove() {
|
public void remove() {
|
||||||
if (canRemove == false) {
|
if (canRemove == false) {
|
||||||
throw new IllegalStateException("Iterator remove() can only be called once after next()");
|
throw new IllegalStateException("Iterator remove() can only be called once after next()");
|
||||||
}
|
}
|
||||||
super.remove(); // removes from maps[0]
|
super.remove(); // removes from maps[0]
|
||||||
parent.maps[1].remove(lastValue);
|
parent.reverseMap.remove(lastValue);
|
||||||
lastValue = null;
|
lastValue = null;
|
||||||
canRemove = false;
|
canRemove = false;
|
||||||
}
|
}
|
||||||
|
@ -533,67 +538,72 @@ public abstract class AbstractDualBidiMap implements BidiMap {
|
||||||
/**
|
/**
|
||||||
* Inner class EntrySet.
|
* Inner class EntrySet.
|
||||||
*/
|
*/
|
||||||
protected static class EntrySet extends View implements Set {
|
protected static class EntrySet<K, V> extends View<K, V, Map.Entry<K, V>> implements Set<Map.Entry<K, V>> {
|
||||||
|
|
||||||
|
/** Serialization version */
|
||||||
|
private static final long serialVersionUID = 4040410962603292348L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new view of the BidiMap.
|
* Constructs a new view of the BidiMap.
|
||||||
*
|
*
|
||||||
* @param parent the parent BidiMap
|
* @param parent the parent BidiMap
|
||||||
*/
|
*/
|
||||||
protected EntrySet(AbstractDualBidiMap parent) {
|
protected EntrySet(AbstractDualBidiMap<K, V> parent) {
|
||||||
super(parent.maps[0].entrySet(), parent);
|
super(parent.normalMap.entrySet(), parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator iterator() {
|
public Iterator<Map.Entry<K, V>> iterator() {
|
||||||
return parent.createEntrySetIterator(super.iterator());
|
return parent.createEntrySetIterator(super.iterator());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean remove(Object obj) {
|
public boolean remove(Object obj) {
|
||||||
if (obj instanceof Map.Entry == false) {
|
if (obj instanceof Map.Entry == false) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Map.Entry entry = (Map.Entry) obj;
|
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) obj;
|
||||||
Object key = entry.getKey();
|
Object key = entry.getKey();
|
||||||
if (parent.containsKey(key)) {
|
if (parent.containsKey(key)) {
|
||||||
Object value = parent.maps[0].get(key);
|
V value = parent.normalMap.get(key);
|
||||||
if (value == null ? entry.getValue() == null : value.equals(entry.getValue())) {
|
if (value == null ? entry.getValue() == null : value.equals(entry.getValue())) {
|
||||||
parent.maps[0].remove(key);
|
parent.normalMap.remove(key);
|
||||||
parent.maps[1].remove(value);
|
parent.reverseMap.remove(value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inner class EntrySetIterator.
|
* Inner class EntrySetIterator.
|
||||||
*/
|
*/
|
||||||
protected static class EntrySetIterator extends AbstractIteratorDecorator {
|
protected static class EntrySetIterator<K, V> extends AbstractIteratorDecorator<Map.Entry<K, V>> {
|
||||||
|
|
||||||
/** The parent map */
|
/** The parent map */
|
||||||
protected final AbstractDualBidiMap parent;
|
protected final AbstractDualBidiMap<K, V> parent;
|
||||||
|
|
||||||
/** The last returned entry */
|
/** The last returned entry */
|
||||||
protected Map.Entry last = null;
|
protected Map.Entry<K, V> last = null;
|
||||||
|
|
||||||
/** Whether remove is allowed at present */
|
/** Whether remove is allowed at present */
|
||||||
protected boolean canRemove = false;
|
protected boolean canRemove = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
* @param iterator the iterator to decorate
|
* @param iterator the iterator to decorate
|
||||||
* @param parent the parent map
|
* @param parent the parent map
|
||||||
*/
|
*/
|
||||||
protected EntrySetIterator(Iterator iterator, AbstractDualBidiMap parent) {
|
protected EntrySetIterator(Iterator<Map.Entry<K, V>> iterator, AbstractDualBidiMap<K, V> parent) {
|
||||||
super(iterator);
|
super(iterator);
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object next() {
|
public Map.Entry<K, V> next() {
|
||||||
last = new MapEntry((Map.Entry) super.next(), parent);
|
last = new MapEntry<K, V>(super.next(), parent);
|
||||||
canRemove = true;
|
canRemove = true;
|
||||||
return last;
|
return last;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove() {
|
public void remove() {
|
||||||
if (canRemove == false) {
|
if (canRemove == false) {
|
||||||
throw new IllegalStateException("Iterator remove() can only be called once after next()");
|
throw new IllegalStateException("Iterator remove() can only be called once after next()");
|
||||||
|
@ -601,7 +611,7 @@ public abstract class AbstractDualBidiMap implements BidiMap {
|
||||||
// store value as remove may change the entry in the decorator (eg.TreeMap)
|
// store value as remove may change the entry in the decorator (eg.TreeMap)
|
||||||
Object value = last.getValue();
|
Object value = last.getValue();
|
||||||
super.remove();
|
super.remove();
|
||||||
parent.maps[1].remove(value);
|
parent.reverseMap.remove(value);
|
||||||
last = null;
|
last = null;
|
||||||
canRemove = false;
|
canRemove = false;
|
||||||
}
|
}
|
||||||
|
@ -610,117 +620,119 @@ public abstract class AbstractDualBidiMap implements BidiMap {
|
||||||
/**
|
/**
|
||||||
* Inner class MapEntry.
|
* Inner class MapEntry.
|
||||||
*/
|
*/
|
||||||
protected static class MapEntry extends AbstractMapEntryDecorator {
|
protected static class MapEntry<K, V> extends AbstractMapEntryDecorator<K, V> {
|
||||||
|
|
||||||
|
/** The parent map */
|
||||||
|
protected final AbstractDualBidiMap<K, V> parent;
|
||||||
|
|
||||||
/** The parent map */
|
|
||||||
protected final AbstractDualBidiMap parent;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
* @param entry the entry to decorate
|
* @param entry the entry to decorate
|
||||||
* @param parent the parent map
|
* @param parent the parent map
|
||||||
*/
|
*/
|
||||||
protected MapEntry(Map.Entry entry, AbstractDualBidiMap parent) {
|
protected MapEntry(Map.Entry<K, V> entry, AbstractDualBidiMap<K, V> parent) {
|
||||||
super(entry);
|
super(entry);
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object setValue(Object value) {
|
public V setValue(V value) {
|
||||||
Object key = MapEntry.this.getKey();
|
K key = MapEntry.this.getKey();
|
||||||
if (parent.maps[1].containsKey(value) &&
|
if (parent.reverseMap.containsKey(value) &&
|
||||||
parent.maps[1].get(value) != key) {
|
parent.reverseMap.get(value) != key) {
|
||||||
throw new IllegalArgumentException("Cannot use setValue() when the object being set is already in the map");
|
throw new IllegalArgumentException("Cannot use setValue() when the object being set is already in the map");
|
||||||
}
|
}
|
||||||
parent.put(key, value);
|
parent.put(key, value);
|
||||||
final Object oldValue = super.setValue(value);
|
final V oldValue = super.setValue(value);
|
||||||
return oldValue;
|
return oldValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inner class MapIterator.
|
* Inner class MapIterator.
|
||||||
*/
|
*/
|
||||||
protected static class BidiMapIterator implements MapIterator, ResettableIterator {
|
protected static class BidiMapIterator<K, V> implements MapIterator<K, V>, ResettableIterator<K> {
|
||||||
|
|
||||||
/** The parent map */
|
/** The parent map */
|
||||||
protected final AbstractDualBidiMap parent;
|
protected final AbstractDualBidiMap<K, V> parent;
|
||||||
|
|
||||||
/** The iterator being wrapped */
|
/** The iterator being wrapped */
|
||||||
protected Iterator iterator;
|
protected Iterator<Map.Entry<K, V>> iterator;
|
||||||
|
|
||||||
/** The last returned entry */
|
/** The last returned entry */
|
||||||
protected Map.Entry last = null;
|
protected Map.Entry<K, V> last = null;
|
||||||
|
|
||||||
/** Whether remove is allowed at present */
|
/** Whether remove is allowed at present */
|
||||||
protected boolean canRemove = false;
|
protected boolean canRemove = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
* @param parent the parent map
|
* @param parent the parent map
|
||||||
*/
|
*/
|
||||||
protected BidiMapIterator(AbstractDualBidiMap parent) {
|
protected BidiMapIterator(AbstractDualBidiMap<K, V> parent) {
|
||||||
super();
|
super();
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.iterator = parent.maps[0].entrySet().iterator();
|
this.iterator = parent.normalMap.entrySet().iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
return iterator.hasNext();
|
return iterator.hasNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object next() {
|
public K next() {
|
||||||
last = (Map.Entry) iterator.next();
|
last = iterator.next();
|
||||||
canRemove = true;
|
canRemove = true;
|
||||||
return last.getKey();
|
return last.getKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove() {
|
public void remove() {
|
||||||
if (canRemove == false) {
|
if (canRemove == false) {
|
||||||
throw new IllegalStateException("Iterator remove() can only be called once after next()");
|
throw new IllegalStateException("Iterator remove() can only be called once after next()");
|
||||||
}
|
}
|
||||||
// store value as remove may change the entry in the decorator (eg.TreeMap)
|
// store value as remove may change the entry in the decorator (eg.TreeMap)
|
||||||
Object value = last.getValue();
|
V value = last.getValue();
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
parent.maps[1].remove(value);
|
parent.reverseMap.remove(value);
|
||||||
last = null;
|
last = null;
|
||||||
canRemove = false;
|
canRemove = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getKey() {
|
public K getKey() {
|
||||||
if (last == null) {
|
if (last == null) {
|
||||||
throw new IllegalStateException("Iterator getKey() can only be called after next() and before remove()");
|
throw new IllegalStateException("Iterator getKey() can only be called after next() and before remove()");
|
||||||
}
|
}
|
||||||
return last.getKey();
|
return last.getKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getValue() {
|
public V getValue() {
|
||||||
if (last == null) {
|
if (last == null) {
|
||||||
throw new IllegalStateException("Iterator getValue() can only be called after next() and before remove()");
|
throw new IllegalStateException("Iterator getValue() can only be called after next() and before remove()");
|
||||||
}
|
}
|
||||||
return last.getValue();
|
return last.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object setValue(Object value) {
|
public V setValue(V value) {
|
||||||
if (last == null) {
|
if (last == null) {
|
||||||
throw new IllegalStateException("Iterator setValue() can only be called after next() and before remove()");
|
throw new IllegalStateException("Iterator setValue() can only be called after next() and before remove()");
|
||||||
}
|
}
|
||||||
if (parent.maps[1].containsKey(value) &&
|
if (parent.reverseMap.containsKey(value) &&
|
||||||
parent.maps[1].get(value) != last.getKey()) {
|
parent.reverseMap.get(value) != last.getKey()) {
|
||||||
throw new IllegalArgumentException("Cannot use setValue() when the object being set is already in the map");
|
throw new IllegalArgumentException("Cannot use setValue() when the object being set is already in the map");
|
||||||
}
|
}
|
||||||
return parent.put(last.getKey(), value);
|
return parent.put(last.getKey(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reset() {
|
public void reset() {
|
||||||
iterator = parent.maps[0].entrySet().iterator();
|
iterator = parent.normalMap.entrySet().iterator();
|
||||||
last = null;
|
last = null;
|
||||||
canRemove = false;
|
canRemove = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
if (last != null) {
|
if (last != null) {
|
||||||
return "MapIterator[" + getKey() + "=" + getValue() + "]";
|
return "MapIterator[" + getKey() + "=" + getValue() + "]";
|
||||||
} else {
|
|
||||||
return "MapIterator[]";
|
|
||||||
}
|
}
|
||||||
|
return "MapIterator[]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue