aboutsummaryrefslogtreecommitdiffstats
path: root/guava/src/com/google/common/collect/RegularImmutableBiMap.java
diff options
context:
space:
mode:
Diffstat (limited to 'guava/src/com/google/common/collect/RegularImmutableBiMap.java')
-rw-r--r--guava/src/com/google/common/collect/RegularImmutableBiMap.java282
1 files changed, 22 insertions, 260 deletions
diff --git a/guava/src/com/google/common/collect/RegularImmutableBiMap.java b/guava/src/com/google/common/collect/RegularImmutableBiMap.java
index b67aa76..dca1f05 100644
--- a/guava/src/com/google/common/collect/RegularImmutableBiMap.java
+++ b/guava/src/com/google/common/collect/RegularImmutableBiMap.java
@@ -16,283 +16,45 @@
package com.google.common.collect;
-import static com.google.common.base.Preconditions.checkNotNull;
-
import com.google.common.annotations.GwtCompatible;
-import java.io.Serializable;
-import java.util.Collection;
-
-import javax.annotation.Nullable;
-
/**
- * Bimap with two or more mappings.
- *
- * @author Louis Wasserman
+ * Bimap with one or more mappings.
+ *
+ * @author Jared Levy
*/
@GwtCompatible(serializable = true, emulated = true)
@SuppressWarnings("serial") // uses writeReplace(), not default serialization
class RegularImmutableBiMap<K, V> extends ImmutableBiMap<K, V> {
- private static class BiMapEntry<K, V> extends ImmutableEntry<K, V> {
- BiMapEntry(K key, V value) {
- super(key, value);
- }
-
- @Nullable
- BiMapEntry<K, V> getNextInKToVBucket() {
- return null;
- }
-
- @Nullable
- BiMapEntry<K, V> getNextInVToKBucket() {
- return null;
- }
- }
-
- private static class NonTerminalBiMapEntry<K, V> extends BiMapEntry<K, V> {
- @Nullable private final BiMapEntry<K, V> nextInKToVBucket;
- @Nullable private final BiMapEntry<K, V> nextInVToKBucket;
-
- NonTerminalBiMapEntry(K key, V value, @Nullable BiMapEntry<K, V> nextInKToVBucket,
- @Nullable BiMapEntry<K, V> nextInVToKBucket) {
- super(key, value);
- this.nextInKToVBucket = nextInKToVBucket;
- this.nextInVToKBucket = nextInVToKBucket;
- }
+ final transient ImmutableMap<K, V> delegate;
+ final transient ImmutableBiMap<V, K> inverse;
- @Override
- @Nullable
- BiMapEntry<K, V> getNextInKToVBucket() {
- return nextInKToVBucket;
- }
-
- @Override
- @Nullable
- BiMapEntry<K, V> getNextInVToKBucket() {
- return nextInVToKBucket;
- }
- }
-
- static final double MAX_LOAD_FACTOR = 1.2;
-
- private transient final BiMapEntry<K, V>[] kToVTable;
- private transient final BiMapEntry<K, V>[] vToKTable;
- private transient final BiMapEntry<K, V>[] entries;
- private transient final int mask;
- private transient final int hashCode;
-
- RegularImmutableBiMap(Collection<? extends Entry<? extends K, ? extends V>> entriesToAdd) {
- int n = entriesToAdd.size();
- int tableSize = Hashing.closedTableSize(n, MAX_LOAD_FACTOR);
- this.mask = tableSize - 1;
- BiMapEntry<K, V>[] kToVTable = createEntryArray(tableSize);
- BiMapEntry<K, V>[] vToKTable = createEntryArray(tableSize);
- BiMapEntry<K, V>[] entries = createEntryArray(n);
- int i = 0;
- int hashCode = 0;
-
- for (Entry<? extends K, ? extends V> entry : entriesToAdd) {
- K key = checkNotNull(entry.getKey());
- V value = checkNotNull(entry.getValue());
-
- int keyHash = key.hashCode();
- int valueHash = value.hashCode();
- int keyBucket = Hashing.smear(keyHash) & mask;
- int valueBucket = Hashing.smear(valueHash) & mask;
-
- BiMapEntry<K, V> nextInKToVBucket = kToVTable[keyBucket];
- for (BiMapEntry<K, V> kToVEntry = nextInKToVBucket; kToVEntry != null;
- kToVEntry = kToVEntry.getNextInKToVBucket()) {
- if (key.equals(kToVEntry.getKey())) {
- throw new IllegalArgumentException("Multiple entries with same key: " +
- entry + " and " + kToVEntry);
- }
- }
- BiMapEntry<K, V> nextInVToKBucket = vToKTable[valueBucket];
- for (BiMapEntry<K, V> vToKEntry = nextInVToKBucket; vToKEntry != null;
- vToKEntry = vToKEntry.getNextInVToKBucket()) {
- if (value.equals(vToKEntry.getValue())) {
- throw new IllegalArgumentException("Multiple entries with same value: "
- + entry + " and " + vToKEntry);
- }
- }
- BiMapEntry<K, V> newEntry =
- (nextInKToVBucket == null && nextInVToKBucket == null)
- ? new BiMapEntry<K, V>(key, value)
- : new NonTerminalBiMapEntry<K, V>(key, value, nextInKToVBucket, nextInVToKBucket);
- kToVTable[keyBucket] = newEntry;
- vToKTable[valueBucket] = newEntry;
- entries[i++] = newEntry;
- hashCode += keyHash ^ valueHash;
- }
-
- this.kToVTable = kToVTable;
- this.vToKTable = vToKTable;
- this.entries = entries;
- this.hashCode = hashCode;
- }
-
- @SuppressWarnings("unchecked")
- private static <K, V> BiMapEntry<K, V>[] createEntryArray(int length) {
- return new BiMapEntry[length];
- }
+ RegularImmutableBiMap(ImmutableMap<K, V> delegate) {
+ this.delegate = delegate;
- @Override
- @Nullable
- public V get(@Nullable Object key) {
- if (key == null) {
- return null;
- }
- int bucket = Hashing.smear(key.hashCode()) & mask;
- for (BiMapEntry<K, V> entry = kToVTable[bucket]; entry != null;
- entry = entry.getNextInKToVBucket()) {
- if (key.equals(entry.getKey())) {
- return entry.getValue();
- }
+ ImmutableMap.Builder<V, K> builder = ImmutableMap.builder();
+ for (Entry<K, V> entry : delegate.entrySet()) {
+ builder.put(entry.getValue(), entry.getKey());
}
- return null;
- }
-
- @Override
- ImmutableSet<Entry<K, V>> createEntrySet() {
- return new ImmutableMapEntrySet<K, V>() {
- @Override
- ImmutableMap<K, V> map() {
- return RegularImmutableBiMap.this;
- }
-
- @Override
- public UnmodifiableIterator<Entry<K, V>> iterator() {
- return asList().iterator();
- }
-
- @Override
- ImmutableList<Entry<K, V>> createAsList() {
- return new RegularImmutableAsList<Entry<K, V>>(this, entries);
- }
-
- @Override
- boolean isHashCodeFast() {
- return true;
- }
-
- @Override
- public int hashCode() {
- return hashCode;
- }
- };
+ ImmutableMap<V, K> backwardMap = builder.build();
+ this.inverse = new RegularImmutableBiMap<V, K>(backwardMap, this);
}
- @Override
- boolean isPartialView() {
- return false;
+ RegularImmutableBiMap(ImmutableMap<K, V> delegate,
+ ImmutableBiMap<V, K> inverse) {
+ this.delegate = delegate;
+ this.inverse = inverse;
}
- @Override
- public int size() {
- return entries.length;
+ @Override ImmutableMap<K, V> delegate() {
+ return delegate;
}
-
- private transient ImmutableBiMap<V, K> inverse;
- @Override
- public ImmutableBiMap<V, K> inverse() {
- ImmutableBiMap<V, K> result = inverse;
- return (result == null) ? inverse = new Inverse() : result;
+ @Override public ImmutableBiMap<V, K> inverse() {
+ return inverse;
}
-
- private final class Inverse extends ImmutableBiMap<V, K> {
-
- @Override
- public int size() {
- return inverse().size();
- }
-
- @Override
- public ImmutableBiMap<K, V> inverse() {
- return RegularImmutableBiMap.this;
- }
-
- @Override
- public K get(@Nullable Object value) {
- if (value == null) {
- return null;
- }
- int bucket = Hashing.smear(value.hashCode()) & mask;
- for (BiMapEntry<K, V> entry = vToKTable[bucket]; entry != null;
- entry = entry.getNextInVToKBucket()) {
- if (value.equals(entry.getValue())) {
- return entry.getKey();
- }
- }
- return null;
- }
-
- @Override
- ImmutableSet<Entry<V, K>> createEntrySet() {
- return new InverseEntrySet();
- }
-
- final class InverseEntrySet extends ImmutableMapEntrySet<V, K> {
- @Override
- ImmutableMap<V, K> map() {
- return Inverse.this;
- }
- @Override
- boolean isHashCodeFast() {
- return true;
- }
-
- @Override
- public int hashCode() {
- return hashCode;
- }
-
- @Override
- public UnmodifiableIterator<Entry<V, K>> iterator() {
- return asList().iterator();
- }
-
- @Override
- ImmutableList<Entry<V, K>> createAsList() {
- return new ImmutableAsList<Entry<V, K>>() {
- @Override
- public Entry<V, K> get(int index) {
- Entry<K, V> entry = entries[index];
- return Maps.immutableEntry(entry.getValue(), entry.getKey());
- }
-
- @Override
- ImmutableCollection<Entry<V, K>> delegateCollection() {
- return InverseEntrySet.this;
- }
- };
- }
- }
-
- @Override
- boolean isPartialView() {
- return false;
- }
-
- @Override
- Object writeReplace() {
- return new InverseSerializedForm<K, V>(RegularImmutableBiMap.this);
- }
- }
-
- private static class InverseSerializedForm<K, V> implements Serializable {
- private final ImmutableBiMap<K, V> forward;
-
- InverseSerializedForm(ImmutableBiMap<K, V> forward) {
- this.forward = forward;
- }
-
- Object readResolve() {
- return forward.inverse();
- }
-
- private static final long serialVersionUID = 1;
+ @Override boolean isPartialView() {
+ return delegate.isPartialView() || inverse.delegate().isPartialView();
}
}