001/*
002 * Copyright (C) 2007 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005 * in compliance with the License. You may obtain a copy of the License at
006 *
007 * http://www.apache.org/licenses/LICENSE-2.0
008 *
009 * Unless required by applicable law or agreed to in writing, software distributed under the License
010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011 * or implied. See the License for the specific language governing permissions and limitations under
012 * the License.
013 */
014
015package com.google.common.collect;
016
017import static com.google.common.base.Preconditions.checkArgument;
018import static com.google.common.base.Preconditions.checkState;
019
020import com.google.common.annotations.GwtCompatible;
021import com.google.common.annotations.GwtIncompatible;
022import com.google.common.base.Objects;
023
024import java.io.IOException;
025import java.io.ObjectInputStream;
026import java.io.ObjectOutputStream;
027import java.io.Serializable;
028import java.util.AbstractMap;
029import java.util.Arrays;
030import java.util.ConcurrentModificationException;
031import java.util.Iterator;
032import java.util.Map;
033import java.util.NoSuchElementException;
034import java.util.Set;
035
036import javax.annotation.Nullable;
037
038/**
039 * A {@link BiMap} backed by two hash tables. This implementation allows null keys and values. A
040 * {@code HashBiMap} and its inverse are both serializable.
041 *
042 * <p>See the Guava User Guide article on <a href=
043 * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#BiMap"> {@code BiMap}
044 * </a>.
045 *
046 * @author Louis Wasserman
047 * @author Mike Bostock
048 * @since 2.0 (imported from Google Collections Library)
049 */
050@GwtCompatible(emulated = true)
051public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K, V>, Serializable {
052
053  /**
054   * Returns a new, empty {@code HashBiMap} with the default initial capacity (16).
055   */
056  public static <K, V> HashBiMap<K, V> create() {
057    return create(16);
058  }
059
060  /**
061   * Constructs a new, empty bimap with the specified expected size.
062   *
063   * @param expectedSize the expected number of entries
064   * @throws IllegalArgumentException if the specified expected size is negative
065   */
066  public static <K, V> HashBiMap<K, V> create(int expectedSize) {
067    return new HashBiMap<K, V>(expectedSize);
068  }
069
070  /**
071   * Constructs a new bimap containing initial values from {@code map}. The bimap is created with an
072   * initial capacity sufficient to hold the mappings in the specified map.
073   */
074  public static <K, V> HashBiMap<K, V> create(Map<? extends K, ? extends V> map) {
075    HashBiMap<K, V> bimap = create(map.size());
076    bimap.putAll(map);
077    return bimap;
078  }
079
080  private static final class BiEntry<K, V> {
081    final K key;
082    final int keyHash;
083
084    final V value;
085    final int valueHash;
086
087    @Nullable
088    BiEntry<K, V> nextInKToVBucket;
089
090    @Nullable
091    BiEntry<K, V> nextInVToKBucket;
092
093    BiEntry(K key, int keyHash, V value, int valueHash) {
094      this.key = key;
095      this.keyHash = keyHash;
096      this.value = value;
097      this.valueHash = valueHash;
098    }
099  }
100
101  private static final double LOAD_FACTOR = 1.0;
102  
103  private transient BiEntry<K, V>[] hashTableKToV;
104  private transient BiEntry<K, V>[] hashTableVToK;
105  private transient int size;
106  private transient int mask;
107  private transient int modCount;
108
109  private HashBiMap(int expectedSize) {
110    init(expectedSize);
111  }
112
113  private void init(int expectedSize) {
114    checkArgument(expectedSize >= 0, "expectedSize must be >= 0 but was %s", expectedSize);
115    int tableSize = Hashing.closedTableSize(expectedSize, LOAD_FACTOR);
116    this.hashTableKToV = createTable(tableSize);
117    this.hashTableVToK = createTable(tableSize);
118    this.mask = tableSize - 1;
119    this.modCount = 0;
120    this.size = 0;
121  }
122
123  /**
124   * Finds and removes {@code entry} from the bucket linked lists in both the
125   * key-to-value direction and the value-to-key direction.
126   */
127  private void delete(BiEntry<K, V> entry) {
128    int keyBucket = entry.keyHash & mask;
129    BiEntry<K, V> prevBucketEntry = null;
130    for (BiEntry<K, V> bucketEntry = hashTableKToV[keyBucket]; true;
131        bucketEntry = bucketEntry.nextInKToVBucket) {
132      if (bucketEntry == entry) {
133        if (prevBucketEntry == null) {
134          hashTableKToV[keyBucket] = entry.nextInKToVBucket;
135        } else {
136          prevBucketEntry.nextInKToVBucket = entry.nextInKToVBucket;
137        }
138        break;
139      }
140      prevBucketEntry = bucketEntry;
141    }
142
143    int valueBucket = entry.valueHash & mask;
144    prevBucketEntry = null;
145    for (BiEntry<K, V> bucketEntry = hashTableVToK[valueBucket];;
146        bucketEntry = bucketEntry.nextInVToKBucket) {
147      if (bucketEntry == entry) {
148        if (prevBucketEntry == null) {
149          hashTableVToK[valueBucket] = entry.nextInVToKBucket;
150        } else {
151          prevBucketEntry.nextInVToKBucket = entry.nextInVToKBucket;
152        }
153        break;
154      }
155      prevBucketEntry = bucketEntry;
156    }
157
158    size--;
159    modCount++;
160  }
161
162  private void insert(BiEntry<K, V> entry) {
163    int keyBucket = entry.keyHash & mask;
164    entry.nextInKToVBucket = hashTableKToV[keyBucket];
165    hashTableKToV[keyBucket] = entry;
166
167    int valueBucket = entry.valueHash & mask;
168    entry.nextInVToKBucket = hashTableVToK[valueBucket];
169    hashTableVToK[valueBucket] = entry;
170
171    size++;
172    modCount++;
173  }
174
175  private static int hash(@Nullable Object o) {
176    return Hashing.smear((o == null) ? 0 : o.hashCode());
177  }
178
179  private BiEntry<K, V> seekByKey(@Nullable Object key, int keyHash) {
180    for (BiEntry<K, V> entry = hashTableKToV[keyHash & mask]; entry != null;
181        entry = entry.nextInKToVBucket) {
182      if (keyHash == entry.keyHash && Objects.equal(key, entry.key)) {
183        return entry;
184      }
185    }
186    return null;
187  }
188
189  private BiEntry<K, V> seekByValue(@Nullable Object value, int valueHash) {
190    for (BiEntry<K, V> entry = hashTableVToK[valueHash & mask]; entry != null;
191        entry = entry.nextInVToKBucket) {
192      if (valueHash == entry.valueHash && Objects.equal(value, entry.value)) {
193        return entry;
194      }
195    }
196    return null;
197  }
198
199  @Override
200  public boolean containsKey(@Nullable Object key) {
201    return seekByKey(key, hash(key)) != null;
202  }
203
204  @Override
205  public boolean containsValue(@Nullable Object value) {
206    return seekByValue(value, hash(value)) != null;
207  }
208
209  @Nullable
210  @Override
211  public V get(@Nullable Object key) {
212    BiEntry<K, V> entry = seekByKey(key, hash(key));
213    return (entry == null) ? null : entry.value;
214  }
215
216  @Override
217  public V put(@Nullable K key, @Nullable V value) {
218    return put(key, value, false);
219  }
220
221  @Override
222  public V forcePut(@Nullable K key, @Nullable V value) {
223    return put(key, value, true);
224  }
225
226  private V put(@Nullable K key, @Nullable V value, boolean force) {
227    int keyHash = hash(key);
228    int valueHash = hash(value);
229
230    BiEntry<K, V> oldEntryForKey = seekByKey(key, keyHash);
231    if (oldEntryForKey != null && valueHash == oldEntryForKey.valueHash
232        && Objects.equal(value, oldEntryForKey.value)) {
233      return value;
234    }
235
236    BiEntry<K, V> oldEntryForValue = seekByValue(value, valueHash);
237    if (oldEntryForValue != null) {
238      if (force) {
239        delete(oldEntryForValue);
240      } else {
241        throw new IllegalArgumentException("value already present: " + value);
242      }
243    }
244
245    if (oldEntryForKey != null) {
246      delete(oldEntryForKey);
247    }
248    BiEntry<K, V> newEntry = new BiEntry<K, V>(key, keyHash, value, valueHash);
249    insert(newEntry);
250    rehashIfNecessary();
251    return (oldEntryForKey == null) ? null : oldEntryForKey.value;
252  }
253
254  @Nullable
255  private K putInverse(@Nullable V value, @Nullable K key, boolean force) {
256    int valueHash = hash(value);
257    int keyHash = hash(key);
258
259    BiEntry<K, V> oldEntryForValue = seekByValue(value, valueHash);
260    if (oldEntryForValue != null && keyHash == oldEntryForValue.keyHash
261        && Objects.equal(key, oldEntryForValue.key)) {
262      return key;
263    }
264
265    BiEntry<K, V> oldEntryForKey = seekByKey(key, keyHash);
266    if (oldEntryForKey != null) {
267      if (force) {
268        delete(oldEntryForKey);
269      } else {
270        throw new IllegalArgumentException("value already present: " + key);
271      }
272    }
273
274    if (oldEntryForValue != null) {
275      delete(oldEntryForValue);
276    }
277    BiEntry<K, V> newEntry = new BiEntry<K, V>(key, keyHash, value, valueHash);
278    insert(newEntry);
279    rehashIfNecessary();
280    return (oldEntryForValue == null) ? null : oldEntryForValue.key;
281  }
282
283  private void rehashIfNecessary() {
284    BiEntry<K, V>[] oldKToV = hashTableKToV;
285    if (Hashing.needsResizing(size, oldKToV.length, LOAD_FACTOR)) {
286      int newTableSize = oldKToV.length * 2;
287
288      this.hashTableKToV = createTable(newTableSize);
289      this.hashTableVToK = createTable(newTableSize);
290      this.mask = newTableSize - 1;
291      this.size = 0;
292
293      for (int bucket = 0; bucket < oldKToV.length; bucket++) {
294        BiEntry<K, V> entry = oldKToV[bucket];
295        while (entry != null) {
296          BiEntry<K, V> nextEntry = entry.nextInKToVBucket;
297          insert(entry);
298          entry = nextEntry;
299        }
300      }
301      this.modCount++;
302    }
303  }
304
305  @SuppressWarnings("unchecked")
306  private BiEntry<K, V>[] createTable(int length) {
307    return new BiEntry[length];
308  }
309
310  @Override
311  public V remove(@Nullable Object key) {
312    BiEntry<K, V> entry = seekByKey(key, hash(key));
313    if (entry == null) {
314      return null;
315    } else {
316      delete(entry);
317      return entry.value;
318    }
319  }
320
321  @Override
322  public void clear() {
323    size = 0;
324    Arrays.fill(hashTableKToV, null);
325    Arrays.fill(hashTableVToK, null);
326    modCount++;
327  }
328
329  @Override
330  public int size() {
331    return size;
332  }
333
334  abstract class Itr<T> implements Iterator<T> {
335    int nextBucket = 0;
336    BiEntry<K, V> next = null;
337    BiEntry<K, V> toRemove = null;
338    int expectedModCount = modCount;
339
340    private void checkForConcurrentModification() {
341      if (modCount != expectedModCount) {
342        throw new ConcurrentModificationException();
343      }
344    }
345
346    @Override
347    public boolean hasNext() {
348      checkForConcurrentModification();
349      if (next != null) {
350        return true;
351      }
352      while (nextBucket < hashTableKToV.length) {
353        if (hashTableKToV[nextBucket] != null) {
354          next = hashTableKToV[nextBucket++];
355          return true;
356        }
357        nextBucket++;
358      }
359      return false;
360    }
361
362    @Override
363    public T next() {
364      checkForConcurrentModification();
365      if (!hasNext()) {
366        throw new NoSuchElementException();
367      }
368
369      BiEntry<K, V> entry = next;
370      next = entry.nextInKToVBucket;
371      toRemove = entry;
372      return output(entry);
373    }
374
375    @Override
376    public void remove() {
377      checkForConcurrentModification();
378      checkState(toRemove != null, "Only one remove() call allowed per call to next");
379      delete(toRemove);
380      expectedModCount = modCount;
381      toRemove = null;
382    }
383
384    abstract T output(BiEntry<K, V> entry);
385  }
386
387  @Override
388  public Set<K> keySet() {
389    return new KeySet();
390  }
391
392  private final class KeySet extends Maps.KeySet<K, V> {
393    @Override
394    Map<K, V> map() {
395      return HashBiMap.this;
396    }
397
398    @Override
399    public Iterator<K> iterator() {
400      return new Itr<K>() {
401        @Override
402        K output(BiEntry<K, V> entry) {
403          return entry.key;
404        }
405      };
406    }
407
408    @Override
409    public boolean remove(@Nullable Object o) {
410      BiEntry<K, V> entry = seekByKey(o, hash(o));
411      if (entry == null) {
412        return false;
413      } else {
414        delete(entry);
415        return true;
416      }
417    }
418  }
419
420  @Override
421  public Set<V> values() {
422    return inverse().keySet();
423  }
424
425  @Override
426  public Set<Entry<K, V>> entrySet() {
427    return new EntrySet();
428  }
429
430  private final class EntrySet extends Maps.EntrySet<K, V> {
431    @Override
432    Map<K, V> map() {
433      return HashBiMap.this;
434    }
435
436    @Override
437    public Iterator<Entry<K, V>> iterator() {
438      return new Itr<Entry<K, V>>() {
439        @Override
440        Entry<K, V> output(BiEntry<K, V> entry) {
441          return new MapEntry(entry);
442        }
443
444        class MapEntry extends AbstractMapEntry<K, V> {
445          BiEntry<K, V> delegate;
446
447          MapEntry(BiEntry<K, V> entry) {
448            this.delegate = entry;
449          }
450
451          @Override public K getKey() {
452            return delegate.key;
453          }
454
455          @Override public V getValue() {
456            return delegate.value;
457          }
458
459          @Override public V setValue(V value) {
460            V oldValue = delegate.value;
461            int valueHash = hash(value);
462            if (valueHash == delegate.valueHash && Objects.equal(value, oldValue)) {
463              return value;
464            }
465            checkArgument(
466                seekByValue(value, valueHash) == null, "value already present: %s", value);
467            delete(delegate);
468            BiEntry<K, V> newEntry =
469                new BiEntry<K, V>(delegate.key, delegate.keyHash, value, valueHash);
470            insert(newEntry);
471            expectedModCount = modCount;
472            if (toRemove == delegate) {
473              toRemove = newEntry;
474            }
475            delegate = newEntry;
476            return oldValue;
477          }
478        }
479      };
480    }
481  }
482
483  private transient BiMap<V, K> inverse;
484
485  @Override
486  public BiMap<V, K> inverse() {
487    return (inverse == null) ? inverse = new Inverse() : inverse;
488  }
489
490  private final class Inverse extends AbstractMap<V, K> implements BiMap<V, K>, Serializable {
491    BiMap<K, V> forward() {
492      return HashBiMap.this;
493    }
494
495    @Override
496    public int size() {
497      return size;
498    }
499
500    @Override
501    public void clear() {
502      forward().clear();
503    }
504
505    @Override
506    public boolean containsKey(@Nullable Object value) {
507      return forward().containsValue(value);
508    }
509
510    @Override
511    public K get(@Nullable Object value) {
512      BiEntry<K, V> entry = seekByValue(value, hash(value));
513      return (entry == null) ? null : entry.key;
514    }
515
516    @Override
517    public K put(@Nullable V value, @Nullable K key) {
518      return putInverse(value, key, false);
519    }
520
521    @Override
522    public K forcePut(@Nullable V value, @Nullable K key) {
523      return putInverse(value, key, true);
524    }
525
526    @Override
527    public K remove(@Nullable Object value) {
528      BiEntry<K, V> entry = seekByValue(value, hash(value));
529      if (entry == null) {
530        return null;
531      } else {
532        delete(entry);
533        return entry.key;
534      }
535    }
536
537    @Override
538    public BiMap<K, V> inverse() {
539      return forward();
540    }
541
542    @Override
543    public Set<V> keySet() {
544      return new InverseKeySet();
545    }
546
547    private final class InverseKeySet extends Maps.KeySet<V, K> {
548      @Override
549      Map<V, K> map() {
550        return Inverse.this;
551      }
552
553      @Override
554      public boolean remove(@Nullable Object o) {
555        BiEntry<K, V> entry = seekByValue(o, hash(o));
556        if (entry == null) {
557          return false;
558        } else {
559          delete(entry);
560          return true;
561        }
562      }
563
564      @Override
565      public Iterator<V> iterator() {
566        return new Itr<V>() {
567          @Override V output(BiEntry<K, V> entry) {
568            return entry.value;
569          }
570        };
571      }
572    }
573
574    @Override
575    public Set<K> values() {
576      return forward().keySet();
577    }
578
579    @Override
580    public Set<Entry<V, K>> entrySet() {
581      return new Maps.EntrySet<V, K>() {
582
583        @Override
584        Map<V, K> map() {
585          return Inverse.this;
586        }
587
588        @Override
589        public Iterator<Entry<V, K>> iterator() {
590          return new Itr<Entry<V, K>>() {
591            @Override
592            Entry<V, K> output(BiEntry<K, V> entry) {
593              return new InverseEntry(entry);
594            }
595
596            class InverseEntry extends AbstractMapEntry<V, K> {
597              BiEntry<K, V> delegate;
598
599              InverseEntry(BiEntry<K, V> entry) {
600                this.delegate = entry;
601              }
602
603              @Override
604              public V getKey() {
605                return delegate.value;
606              }
607
608              @Override
609              public K getValue() {
610                return delegate.key;
611              }
612
613              @Override
614              public K setValue(K key) {
615                K oldKey = delegate.key;
616                int keyHash = hash(key);
617                if (keyHash == delegate.keyHash && Objects.equal(key, oldKey)) {
618                  return key;
619                }
620                checkArgument(seekByKey(key, keyHash) == null, "value already present: %s", key);
621                delete(delegate);
622                BiEntry<K, V> newEntry =
623                    new BiEntry<K, V>(key, keyHash, delegate.value, delegate.valueHash);
624                insert(newEntry);
625                expectedModCount = modCount;
626                // This is safe because entries can only get bumped up to earlier in the iteration,
627                // so they can't get revisited.
628                return oldKey;
629              }
630            }
631          };
632        }
633      };
634    }
635
636    Object writeReplace() {
637      return new InverseSerializedForm<K, V>(HashBiMap.this);
638    }
639  }
640
641  private static final class InverseSerializedForm<K, V> implements Serializable {
642    private final HashBiMap<K, V> bimap;
643
644    InverseSerializedForm(HashBiMap<K, V> bimap) {
645      this.bimap = bimap;
646    }
647
648    Object readResolve() {
649      return bimap.inverse();
650    }
651  }
652
653  /**
654   * @serialData the number of entries, first key, first value, second key, second value, and so on.
655   */
656  @GwtIncompatible("java.io.ObjectOutputStream")
657  private void writeObject(ObjectOutputStream stream) throws IOException {
658    stream.defaultWriteObject();
659    Serialization.writeMap(this, stream);
660  }
661
662  @GwtIncompatible("java.io.ObjectInputStream")
663  private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
664    stream.defaultReadObject();
665    int size = Serialization.readCount(stream);
666    init(size);
667    Serialization.populateMap(this, stream, size);
668  }
669
670  @GwtIncompatible("Not needed in emulated source")
671  private static final long serialVersionUID = 0;
672}