1090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson/* 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2007 The Guava Authors 3090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 4090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 5090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * you may not use this file except in compliance with the License. 6090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * You may obtain a copy of the License at 7090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 8090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 9090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 10090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Unless required by applicable law or agreed to in writing, software 11090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 12090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * See the License for the specific language governing permissions and 14090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * limitations under the License. 15090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 16090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 17090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonpackage com.google.common.collect; 18090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 19090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport static com.google.common.base.Preconditions.checkArgument; 20090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport static com.google.common.base.Preconditions.checkState; 21090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtCompatible; 231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtIncompatible; 241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Objects; 251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 26090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.io.IOException; 27090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.io.ObjectInputStream; 28090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.io.ObjectOutputStream; 29090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.io.Serializable; 30090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.util.Collection; 31090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.util.Iterator; 32090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.util.Map; 33090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.util.Set; 34090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 35090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport javax.annotation.Nullable; 36090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 37090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson/** 38090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * A general-purpose bimap implementation using any two backing {@code Map} 39090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * instances. 40090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 41090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * <p>Note that this class contains {@code equals()} calls that keep it from 42090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * supporting {@code IdentityHashMap} backing maps. 43090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 44090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @author Kevin Bourrillion 45090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @author Mike Bostock 46090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@GwtCompatible(emulated = true) 48090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonabstract class AbstractBiMap<K, V> extends ForwardingMap<K, V> 49090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson implements BiMap<K, V>, Serializable { 50090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 51090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private transient Map<K, V> delegate; 52090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private transient AbstractBiMap<V, K> inverse; 53090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 54090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** Package-private constructor for creating a map-backed bimap. */ 55090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson AbstractBiMap(Map<K, V> forward, Map<V, K> backward) { 56090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson setDelegates(forward, backward); 57090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 58090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 59090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** Private constructor for inverse bimap. */ 60090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private AbstractBiMap(Map<K, V> backward, AbstractBiMap<V, K> forward) { 61090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson delegate = backward; 62090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson inverse = forward; 63090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 64090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 65090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override protected Map<K, V> delegate() { 66090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return delegate; 67090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 68090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 69090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** 70090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Specifies the delegate maps going in each direction. Called by the 71090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * constructor and by subclasses during deserialization. 72090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 73090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson void setDelegates(Map<K, V> forward, Map<V, K> backward) { 74090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson checkState(delegate == null); 75090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson checkState(inverse == null); 76090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson checkArgument(forward.isEmpty()); 77090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson checkArgument(backward.isEmpty()); 78090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson checkArgument(forward != backward); 79090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson delegate = forward; 80090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson inverse = new Inverse<V, K>(backward, this); 81090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 82090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 83090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson void setInverse(AbstractBiMap<V, K> inverse) { 84090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson this.inverse = inverse; 85090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 86090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 87090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson // Query Operations (optimizations) 88090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 89090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public boolean containsValue(Object value) { 90090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return inverse.containsKey(value); 91090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 92090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 93090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson // Modification Operations 94090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 95090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public V put(K key, V value) { 96090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return putInBothMaps(key, value, false); 97090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 98090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 100090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson public V forcePut(K key, V value) { 101090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return putInBothMaps(key, value, true); 102090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 103090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 104090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private V putInBothMaps(@Nullable K key, @Nullable V value, boolean force) { 105090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson boolean containedKey = containsKey(key); 106090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson if (containedKey && Objects.equal(value, get(key))) { 107090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return value; 108090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 109090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson if (force) { 110090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson inverse().remove(value); 111090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } else { 112090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson checkArgument(!containsValue(value), "value already present: %s", value); 113090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 114090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson V oldValue = delegate.put(key, value); 115090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson updateInverseMap(key, containedKey, oldValue, value); 116090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return oldValue; 117090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 118090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 119090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private void updateInverseMap( 120090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson K key, boolean containedKey, V oldValue, V newValue) { 121090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson if (containedKey) { 122090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson removeFromInverseMap(oldValue); 123090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 124090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson inverse.delegate.put(newValue, key); 125090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 126090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 127090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public V remove(Object key) { 128090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return containsKey(key) ? removeFromBothMaps(key) : null; 129090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 130090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 131090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private V removeFromBothMaps(Object key) { 132090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson V oldValue = delegate.remove(key); 133090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson removeFromInverseMap(oldValue); 134090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return oldValue; 135090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 136090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 137090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private void removeFromInverseMap(V oldValue) { 138090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson inverse.delegate.remove(oldValue); 139090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 140090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 141090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson // Bulk Operations 142090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 143090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public void putAll(Map<? extends K, ? extends V> map) { 144090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson for (Entry<? extends K, ? extends V> entry : map.entrySet()) { 145090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson put(entry.getKey(), entry.getValue()); 146090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 147090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 148090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 149090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public void clear() { 150090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson delegate.clear(); 151090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson inverse.delegate.clear(); 152090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 153090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 154090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson // Views 155090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 157090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson public BiMap<V, K> inverse() { 158090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return inverse; 159090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 160090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 161090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private transient Set<K> keySet; 162090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 163090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public Set<K> keySet() { 164090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson Set<K> result = keySet; 165090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return (result == null) ? keySet = new KeySet() : result; 166090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 167090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 168090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private class KeySet extends ForwardingSet<K> { 169090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override protected Set<K> delegate() { 170090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return delegate.keySet(); 171090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 172090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 173090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public void clear() { 174090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson AbstractBiMap.this.clear(); 175090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 176090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 177090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public boolean remove(Object key) { 178090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson if (!contains(key)) { 179090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return false; 180090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 181090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson removeFromBothMaps(key); 182090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return true; 183090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 184090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 185090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public boolean removeAll(Collection<?> keysToRemove) { 1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return standardRemoveAll(keysToRemove); 187090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 188090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 189090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public boolean retainAll(Collection<?> keysToRetain) { 1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return standardRetainAll(keysToRetain); 191090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 192090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 193090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public Iterator<K> iterator() { 194090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson final Iterator<Entry<K, V>> iterator = delegate.entrySet().iterator(); 195090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return new Iterator<K>() { 196090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson Entry<K, V> entry; 197090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 199090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson public boolean hasNext() { 200090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return iterator.hasNext(); 201090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 203090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson public K next() { 204090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson entry = iterator.next(); 205090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return entry.getKey(); 206090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 208090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson public void remove() { 209090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson checkState(entry != null); 210090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson V value = entry.getValue(); 211090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson iterator.remove(); 212090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson removeFromInverseMap(value); 213090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 214090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson }; 215090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 216090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 217090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 218090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private transient Set<V> valueSet; 219090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 220090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public Set<V> values() { 221090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /* 222090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * We can almost reuse the inverse's keySet, except we have to fix the 223090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * iteration order so that it is consistent with the forward map. 224090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 225090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson Set<V> result = valueSet; 226090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return (result == null) ? valueSet = new ValueSet() : result; 227090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 228090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 229090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private class ValueSet extends ForwardingSet<V> { 230090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson final Set<V> valuesDelegate = inverse.keySet(); 231090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 232090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override protected Set<V> delegate() { 233090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return valuesDelegate; 234090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 235090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 236090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public Iterator<V> iterator() { 237090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson final Iterator<V> iterator = delegate.values().iterator(); 238090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return new Iterator<V>() { 239090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson V valueToRemove; 240090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public boolean hasNext() { 242090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return iterator.hasNext(); 243090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 244090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public V next() { 246090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return valueToRemove = iterator.next(); 247090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 248090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public void remove() { 250090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson iterator.remove(); 251090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson removeFromInverseMap(valueToRemove); 252090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 253090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson }; 254090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 255090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 256090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public Object[] toArray() { 2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return standardToArray(); 258090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 259090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 260090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public <T> T[] toArray(T[] array) { 2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return standardToArray(array); 262090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 263090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 264090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public String toString() { 2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return standardToString(); 266090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 267090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 268090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 269090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private transient Set<Entry<K, V>> entrySet; 270090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 271090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public Set<Entry<K, V>> entrySet() { 272090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson Set<Entry<K, V>> result = entrySet; 273090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return (result == null) ? entrySet = new EntrySet() : result; 274090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 275090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 276090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private class EntrySet extends ForwardingSet<Entry<K, V>> { 277090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson final Set<Entry<K, V>> esDelegate = delegate.entrySet(); 278090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 279090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override protected Set<Entry<K, V>> delegate() { 280090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return esDelegate; 281090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 282090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 283090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public void clear() { 284090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson AbstractBiMap.this.clear(); 285090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 286090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 287090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public boolean remove(Object object) { 2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (!esDelegate.contains(object)) { 289090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return false; 290090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 2911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // safe because esDelgate.contains(object). 293090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson Entry<?, ?> entry = (Entry<?, ?>) object; 294090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson inverse.delegate.remove(entry.getValue()); 2951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /* 2961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Remove the mapping in inverse before removing from esDelegate because 2971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * if entry is part of esDelegate, entry might be invalidated after the 2981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * mapping is removed from esDelegate. 2991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 3001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert esDelegate.remove(entry); 301090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return true; 302090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 303090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 304090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public Iterator<Entry<K, V>> iterator() { 305090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson final Iterator<Entry<K, V>> iterator = esDelegate.iterator(); 306090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return new Iterator<Entry<K, V>>() { 307090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson Entry<K, V> entry; 308090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 3091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public boolean hasNext() { 310090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return iterator.hasNext(); 311090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 312090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 3131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public Entry<K, V> next() { 314090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson entry = iterator.next(); 315090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson final Entry<K, V> finalEntry = entry; 316090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 317090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return new ForwardingMapEntry<K, V>() { 318090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override protected Entry<K, V> delegate() { 319090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return finalEntry; 320090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 321090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 322090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public V setValue(V value) { 323090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson // Preconditions keep the map and inverse consistent. 324090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson checkState(contains(this), "entry no longer in map"); 325090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson // similar to putInBothMaps, but set via entry 326090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson if (Objects.equal(value, getValue())) { 327090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return value; 328090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 329090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson checkArgument(!containsValue(value), 330090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson "value already present: %s", value); 331090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson V oldValue = finalEntry.setValue(value); 332090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson checkState(Objects.equal(value, get(getKey())), 333090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson "entry no longer in map"); 334090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson updateInverseMap(getKey(), true, oldValue, value); 335090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return oldValue; 336090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 337090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson }; 338090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 339090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 3401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public void remove() { 341090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson checkState(entry != null); 342090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson V value = entry.getValue(); 343090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson iterator.remove(); 344090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson removeFromInverseMap(value); 345090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 346090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson }; 347090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 348090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 349090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson // See java.util.Collections.CheckedEntrySet for details on attacks. 350090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 351090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public Object[] toArray() { 3521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return standardToArray(); 353090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 354090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public <T> T[] toArray(T[] array) { 3551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return standardToArray(array); 356090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 357090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public boolean contains(Object o) { 358090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return Maps.containsEntryImpl(delegate(), o); 359090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 360090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public boolean containsAll(Collection<?> c) { 3611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return standardContainsAll(c); 362090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 363090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public boolean removeAll(Collection<?> c) { 3641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return standardRemoveAll(c); 365090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 366090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public boolean retainAll(Collection<?> c) { 3671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return standardRetainAll(c); 368090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 369090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 370090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 371090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** The inverse of any other {@code AbstractBiMap} subclass. */ 372090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private static class Inverse<K, V> extends AbstractBiMap<K, V> { 373090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private Inverse(Map<K, V> backward, AbstractBiMap<V, K> forward) { 374090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson super(backward, forward); 375090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 376090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 377090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /* 378090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Serialization stores the forward bimap, the inverse of this inverse. 379090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Deserialization calls inverse() on the forward bimap and returns that 380090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * inverse. 381090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 382090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * If a bimap and its inverse are serialized together, the deserialized 383090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * instances have inverse() methods that return the other. 384090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 385090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 386090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** 387090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @serialData the forward bimap 388090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 3891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @GwtIncompatible("java.io.ObjectOuputStream") 390090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private void writeObject(ObjectOutputStream stream) throws IOException { 391090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson stream.defaultWriteObject(); 392090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson stream.writeObject(inverse()); 393090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 394090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 3951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @GwtIncompatible("java.io.ObjectInputStream") 396090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @SuppressWarnings("unchecked") // reading data stored by writeObject 397090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private void readObject(ObjectInputStream stream) 398090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson throws IOException, ClassNotFoundException { 399090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson stream.defaultReadObject(); 400090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson setInverse((AbstractBiMap<V, K>) stream.readObject()); 401090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 402090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 4031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @GwtIncompatible("Not needed in the emulated source.") 404090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson Object readResolve() { 405090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return inverse().inverse(); 406090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 407090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 4081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @GwtIncompatible("Not needed in emulated source.") 409090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private static final long serialVersionUID = 0; 410090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 411090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 4121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @GwtIncompatible("Not needed in emulated source.") 413090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private static final long serialVersionUID = 0; 414090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson} 415