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