![JAR search and dependency download from the Maven repository](/logo.png)
com.google.common.collect.RegularImmutableBiMap Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of guava Show documentation
Show all versions of guava Show documentation
Guava is a suite of core and expanded libraries that include
utility classes, google's collections, io classes, and much
much more.
Guava has two code dependencies - javax.annotation
per the JSR-305 spec and javax.inject per the JSR-330 spec.
This is a fork of Guava 14.0.1 for Hudson.
The newest version!
/*
* Copyright (C) 2008 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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
*/
@GwtCompatible(serializable = true, emulated = true)
@SuppressWarnings("serial") // uses writeReplace(), not default serialization
class RegularImmutableBiMap extends ImmutableBiMap {
private static class BiMapEntry extends ImmutableEntry {
BiMapEntry(K key, V value) {
super(key, value);
}
@Nullable
BiMapEntry getNextInKToVBucket() {
return null;
}
@Nullable
BiMapEntry getNextInVToKBucket() {
return null;
}
}
private static class NonTerminalBiMapEntry extends BiMapEntry {
@Nullable private final BiMapEntry nextInKToVBucket;
@Nullable private final BiMapEntry nextInVToKBucket;
NonTerminalBiMapEntry(K key, V value, @Nullable BiMapEntry nextInKToVBucket,
@Nullable BiMapEntry nextInVToKBucket) {
super(key, value);
this.nextInKToVBucket = nextInKToVBucket;
this.nextInVToKBucket = nextInVToKBucket;
}
@Override
@Nullable
BiMapEntry getNextInKToVBucket() {
return nextInKToVBucket;
}
@Override
@Nullable
BiMapEntry getNextInVToKBucket() {
return nextInVToKBucket;
}
}
static final double MAX_LOAD_FACTOR = 1.2;
private transient final BiMapEntry[] kToVTable;
private transient final BiMapEntry[] vToKTable;
private transient final BiMapEntry[] 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[] kToVTable = createEntryArray(tableSize);
BiMapEntry[] vToKTable = createEntryArray(tableSize);
BiMapEntry[] 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 nextInKToVBucket = kToVTable[keyBucket];
for (BiMapEntry kToVEntry = nextInKToVBucket; kToVEntry != null;
kToVEntry = kToVEntry.getNextInKToVBucket()) {
if (key.equals(kToVEntry.getKey())) {
throw new IllegalArgumentException("Multiple entries with same key: " +
entry + " and " + kToVEntry);
}
}
BiMapEntry nextInVToKBucket = vToKTable[valueBucket];
for (BiMapEntry vToKEntry = nextInVToKBucket; vToKEntry != null;
vToKEntry = vToKEntry.getNextInVToKBucket()) {
if (value.equals(vToKEntry.getValue())) {
throw new IllegalArgumentException("Multiple entries with same value: "
+ entry + " and " + vToKEntry);
}
}
BiMapEntry newEntry =
(nextInKToVBucket == null && nextInVToKBucket == null)
? new BiMapEntry(key, value)
: new NonTerminalBiMapEntry(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 BiMapEntry[] createEntryArray(int length) {
return new BiMapEntry[length];
}
@Override
@Nullable
public V get(@Nullable Object key) {
if (key == null) {
return null;
}
int bucket = Hashing.smear(key.hashCode()) & mask;
for (BiMapEntry entry = kToVTable[bucket]; entry != null;
entry = entry.getNextInKToVBucket()) {
if (key.equals(entry.getKey())) {
return entry.getValue();
}
}
return null;
}
@Override
ImmutableSet> createEntrySet() {
return new ImmutableMapEntrySet() {
@Override
ImmutableMap map() {
return RegularImmutableBiMap.this;
}
@Override
public UnmodifiableIterator> iterator() {
return asList().iterator();
}
@Override
ImmutableList> createAsList() {
return new RegularImmutableAsList>(this, entries);
}
@Override
boolean isHashCodeFast() {
return true;
}
@Override
public int hashCode() {
return hashCode;
}
};
}
@Override
boolean isPartialView() {
return false;
}
@Override
public int size() {
return entries.length;
}
private transient ImmutableBiMap inverse;
@Override
public ImmutableBiMap inverse() {
ImmutableBiMap result = inverse;
return (result == null) ? inverse = new Inverse() : result;
}
private final class Inverse extends ImmutableBiMap {
@Override
public int size() {
return inverse().size();
}
@Override
public ImmutableBiMap 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 entry = vToKTable[bucket]; entry != null;
entry = entry.getNextInVToKBucket()) {
if (value.equals(entry.getValue())) {
return entry.getKey();
}
}
return null;
}
@Override
ImmutableSet> createEntrySet() {
return new InverseEntrySet();
}
final class InverseEntrySet extends ImmutableMapEntrySet {
@Override
ImmutableMap map() {
return Inverse.this;
}
@Override
boolean isHashCodeFast() {
return true;
}
@Override
public int hashCode() {
return hashCode;
}
@Override
public UnmodifiableIterator> iterator() {
return asList().iterator();
}
@Override
ImmutableList> createAsList() {
return new ImmutableAsList>() {
@Override
public Entry get(int index) {
Entry entry = entries[index];
return Maps.immutableEntry(entry.getValue(), entry.getKey());
}
@Override
ImmutableCollection> delegateCollection() {
return InverseEntrySet.this;
}
};
}
}
@Override
boolean isPartialView() {
return false;
}
@Override
Object writeReplace() {
return new InverseSerializedForm(RegularImmutableBiMap.this);
}
}
private static class InverseSerializedForm implements Serializable {
private final ImmutableBiMap forward;
InverseSerializedForm(ImmutableBiMap forward) {
this.forward = forward;
}
Object readResolve() {
return forward.inverse();
}
private static final long serialVersionUID = 1;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy