AbstractBiMap.java revision 090f9b4c879985bc747c214f82c62471e60c7742
1090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson/* 2090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Copyright (C) 2007 Google Inc. 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 com.google.common.annotations.GwtCompatible; 20090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport com.google.common.base.Objects; 21090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport static com.google.common.base.Preconditions.checkArgument; 22090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport static com.google.common.base.Preconditions.checkState; 23090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 24090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.io.IOException; 25090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.io.ObjectInputStream; 26090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.io.ObjectOutputStream; 27090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.io.Serializable; 28090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.util.Collection; 29090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.util.Iterator; 30090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.util.Map; 31090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.util.Set; 32090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 33090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport javax.annotation.Nullable; 34090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 35090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson/** 36090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * A general-purpose bimap implementation using any two backing {@code Map} 37090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * instances. 38090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 39090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * <p>Note that this class contains {@code equals()} calls that keep it from 40090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * supporting {@code IdentityHashMap} backing maps. 41090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 42090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @author Kevin Bourrillion 43090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @author Mike Bostock 44090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 45090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson@GwtCompatible 46090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonabstract class AbstractBiMap<K, V> extends ForwardingMap<K, V> 47090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson implements BiMap<K, V>, Serializable { 48090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 49090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private transient Map<K, V> delegate; 50090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private transient AbstractBiMap<V, K> inverse; 51090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 52090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** Package-private constructor for creating a map-backed bimap. */ 53090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson AbstractBiMap(Map<K, V> forward, Map<V, K> backward) { 54090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson setDelegates(forward, backward); 55090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 56090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 57090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** Private constructor for inverse bimap. */ 58090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private AbstractBiMap(Map<K, V> backward, AbstractBiMap<V, K> forward) { 59090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson delegate = backward; 60090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson inverse = forward; 61090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 62090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 63090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override protected Map<K, V> delegate() { 64090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return delegate; 65090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 66090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 67090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** 68090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Specifies the delegate maps going in each direction. Called by the 69090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * constructor and by subclasses during deserialization. 70090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 71090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson void setDelegates(Map<K, V> forward, Map<V, K> backward) { 72090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson checkState(delegate == null); 73090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson checkState(inverse == null); 74090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson checkArgument(forward.isEmpty()); 75090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson checkArgument(backward.isEmpty()); 76090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson checkArgument(forward != backward); 77090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson delegate = forward; 78090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson inverse = new Inverse<V, K>(backward, this); 79090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 80090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 81090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson void setInverse(AbstractBiMap<V, K> inverse) { 82090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson this.inverse = inverse; 83090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 84090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 85090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson // Query Operations (optimizations) 86090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 87090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public boolean containsValue(Object value) { 88090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return inverse.containsKey(value); 89090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 90090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 91090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson // Modification Operations 92090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 93090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public V put(K key, V value) { 94090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return putInBothMaps(key, value, false); 95090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 96090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 97090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson public V forcePut(K key, V value) { 98090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return putInBothMaps(key, value, true); 99090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 100090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 101090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private V putInBothMaps(@Nullable K key, @Nullable V value, boolean force) { 102090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson boolean containedKey = containsKey(key); 103090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson if (containedKey && Objects.equal(value, get(key))) { 104090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return value; 105090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 106090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson if (force) { 107090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson inverse().remove(value); 108090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } else { 109090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson checkArgument(!containsValue(value), "value already present: %s", value); 110090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 111090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson V oldValue = delegate.put(key, value); 112090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson updateInverseMap(key, containedKey, oldValue, value); 113090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return oldValue; 114090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 115090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 116090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private void updateInverseMap( 117090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson K key, boolean containedKey, V oldValue, V newValue) { 118090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson if (containedKey) { 119090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson removeFromInverseMap(oldValue); 120090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 121090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson inverse.delegate.put(newValue, key); 122090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 123090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 124090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public V remove(Object key) { 125090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return containsKey(key) ? removeFromBothMaps(key) : null; 126090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 127090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 128090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private V removeFromBothMaps(Object key) { 129090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson V oldValue = delegate.remove(key); 130090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson removeFromInverseMap(oldValue); 131090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return oldValue; 132090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 133090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 134090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private void removeFromInverseMap(V oldValue) { 135090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson inverse.delegate.remove(oldValue); 136090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 137090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 138090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson // Bulk Operations 139090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 140090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public void putAll(Map<? extends K, ? extends V> map) { 141090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson for (Entry<? extends K, ? extends V> entry : map.entrySet()) { 142090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson put(entry.getKey(), entry.getValue()); 143090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 144090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 145090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 146090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public void clear() { 147090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson delegate.clear(); 148090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson inverse.delegate.clear(); 149090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 150090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 151090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson // Views 152090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 153090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson public BiMap<V, K> inverse() { 154090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return inverse; 155090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 156090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 157090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private transient Set<K> keySet; 158090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 159090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public Set<K> keySet() { 160090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson Set<K> result = keySet; 161090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return (result == null) ? keySet = new KeySet() : result; 162090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 163090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 164090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private class KeySet extends ForwardingSet<K> { 165090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override protected Set<K> delegate() { 166090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return delegate.keySet(); 167090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 168090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 169090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public void clear() { 170090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson AbstractBiMap.this.clear(); 171090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 172090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 173090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public boolean remove(Object key) { 174090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson if (!contains(key)) { 175090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return false; 176090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 177090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson removeFromBothMaps(key); 178090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return true; 179090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 180090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 181090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public boolean removeAll(Collection<?> keysToRemove) { 182090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return Iterators.removeAll(iterator(), keysToRemove); 183090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 184090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 185090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public boolean retainAll(Collection<?> keysToRetain) { 186090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return Iterators.retainAll(iterator(), keysToRetain); 187090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 188090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 189090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public Iterator<K> iterator() { 190090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson final Iterator<Entry<K, V>> iterator = delegate.entrySet().iterator(); 191090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return new Iterator<K>() { 192090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson Entry<K, V> entry; 193090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 194090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson public boolean hasNext() { 195090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return iterator.hasNext(); 196090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 197090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson public K next() { 198090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson entry = iterator.next(); 199090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return entry.getKey(); 200090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 201090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson public void remove() { 202090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson checkState(entry != null); 203090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson V value = entry.getValue(); 204090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson iterator.remove(); 205090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson removeFromInverseMap(value); 206090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 207090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson }; 208090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 209090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 210090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 211090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private transient Set<V> valueSet; 212090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 213090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public Set<V> values() { 214090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /* 215090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * We can almost reuse the inverse's keySet, except we have to fix the 216090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * iteration order so that it is consistent with the forward map. 217090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 218090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson Set<V> result = valueSet; 219090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return (result == null) ? valueSet = new ValueSet() : result; 220090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 221090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 222090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private class ValueSet extends ForwardingSet<V> { 223090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson final Set<V> valuesDelegate = inverse.keySet(); 224090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 225090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override protected Set<V> delegate() { 226090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return valuesDelegate; 227090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 228090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 229090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public Iterator<V> iterator() { 230090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson final Iterator<V> iterator = delegate.values().iterator(); 231090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return new Iterator<V>() { 232090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson V valueToRemove; 233090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 234090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /*@Override*/ public boolean hasNext() { 235090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return iterator.hasNext(); 236090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 237090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 238090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /*@Override*/ public V next() { 239090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return valueToRemove = iterator.next(); 240090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 241090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 242090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /*@Override*/ public void remove() { 243090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson iterator.remove(); 244090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson removeFromInverseMap(valueToRemove); 245090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 246090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson }; 247090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 248090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 249090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public Object[] toArray() { 250090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return ObjectArrays.toArrayImpl(this); 251090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 252090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 253090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public <T> T[] toArray(T[] array) { 254090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return ObjectArrays.toArrayImpl(this, array); 255090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 256090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 257090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public String toString() { 258090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return Iterators.toString(iterator()); 259090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 260090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 261090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 262090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private transient Set<Entry<K, V>> entrySet; 263090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 264090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public Set<Entry<K, V>> entrySet() { 265090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson Set<Entry<K, V>> result = entrySet; 266090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return (result == null) ? entrySet = new EntrySet() : result; 267090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 268090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 269090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private class EntrySet extends ForwardingSet<Entry<K, V>> { 270090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson final Set<Entry<K, V>> esDelegate = delegate.entrySet(); 271090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 272090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override protected Set<Entry<K, V>> delegate() { 273090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return esDelegate; 274090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 275090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 276090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public void clear() { 277090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson AbstractBiMap.this.clear(); 278090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 279090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 280090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public boolean remove(Object object) { 281090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson if (!esDelegate.remove(object)) { 282090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return false; 283090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 284090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson Entry<?, ?> entry = (Entry<?, ?>) object; 285090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson inverse.delegate.remove(entry.getValue()); 286090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return true; 287090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 288090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 289090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public Iterator<Entry<K, V>> iterator() { 290090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson final Iterator<Entry<K, V>> iterator = esDelegate.iterator(); 291090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return new Iterator<Entry<K, V>>() { 292090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson Entry<K, V> entry; 293090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 294090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /*@Override*/ public boolean hasNext() { 295090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return iterator.hasNext(); 296090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 297090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 298090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /*@Override*/ public Entry<K, V> next() { 299090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson entry = iterator.next(); 300090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson final Entry<K, V> finalEntry = entry; 301090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 302090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return new ForwardingMapEntry<K, V>() { 303090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override protected Entry<K, V> delegate() { 304090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return finalEntry; 305090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 306090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 307090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public V setValue(V value) { 308090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson // Preconditions keep the map and inverse consistent. 309090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson checkState(contains(this), "entry no longer in map"); 310090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson // similar to putInBothMaps, but set via entry 311090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson if (Objects.equal(value, getValue())) { 312090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return value; 313090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 314090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson checkArgument(!containsValue(value), 315090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson "value already present: %s", value); 316090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson V oldValue = finalEntry.setValue(value); 317090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson checkState(Objects.equal(value, get(getKey())), 318090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson "entry no longer in map"); 319090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson updateInverseMap(getKey(), true, oldValue, value); 320090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return oldValue; 321090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 322090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson }; 323090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 324090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 325090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /*@Override*/ public void remove() { 326090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson checkState(entry != null); 327090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson V value = entry.getValue(); 328090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson iterator.remove(); 329090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson removeFromInverseMap(value); 330090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 331090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson }; 332090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 333090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 334090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson // See java.util.Collections.CheckedEntrySet for details on attacks. 335090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 336090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public Object[] toArray() { 337090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return ObjectArrays.toArrayImpl(this); 338090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 339090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public <T> T[] toArray(T[] array) { 340090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return ObjectArrays.toArrayImpl(this, array); 341090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 342090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public boolean contains(Object o) { 343090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return Maps.containsEntryImpl(delegate(), o); 344090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 345090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public boolean containsAll(Collection<?> c) { 346090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return Collections2.containsAll(this, c); 347090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 348090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public boolean removeAll(Collection<?> c) { 349090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return Iterators.removeAll(iterator(), c); 350090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 351090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @Override public boolean retainAll(Collection<?> c) { 352090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return Iterators.retainAll(iterator(), c); 353090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 354090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 355090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 356090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** The inverse of any other {@code AbstractBiMap} subclass. */ 357090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private static class Inverse<K, V> extends AbstractBiMap<K, V> { 358090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private Inverse(Map<K, V> backward, AbstractBiMap<V, K> forward) { 359090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson super(backward, forward); 360090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 361090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 362090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /* 363090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Serialization stores the forward bimap, the inverse of this inverse. 364090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Deserialization calls inverse() on the forward bimap and returns that 365090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * inverse. 366090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * 367090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * If a bimap and its inverse are serialized together, the deserialized 368090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * instances have inverse() methods that return the other. 369090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 370090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 371090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson /** 372090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @serialData the forward bimap 373090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */ 374090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private void writeObject(ObjectOutputStream stream) throws IOException { 375090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson stream.defaultWriteObject(); 376090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson stream.writeObject(inverse()); 377090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 378090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 379090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson @SuppressWarnings("unchecked") // reading data stored by writeObject 380090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private void readObject(ObjectInputStream stream) 381090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson throws IOException, ClassNotFoundException { 382090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson stream.defaultReadObject(); 383090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson setInverse((AbstractBiMap<V, K>) stream.readObject()); 384090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 385090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 386090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson Object readResolve() { 387090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson return inverse().inverse(); 388090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 389090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 390090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private static final long serialVersionUID = 0; 391090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson } 392090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson 393090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson private static final long serialVersionUID = 0; 394090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson} 395