static <K, V> RegularImmutableBiMap<K, V> fromEntryArray(int n, Entry<K, V>[] entryArray) { checkPositionIndex(n, entryArray.length); int tableSize = Hashing.closedTableSize(n, MAX_LOAD_FACTOR); int mask = tableSize - 1; ImmutableMapEntry<K, V>[] keyTable = createEntryArray(tableSize); ImmutableMapEntry<K, V>[] valueTable = createEntryArray(tableSize); Entry<K, V>[] entries; if (n == entryArray.length) { entries = entryArray; } else { entries = createEntryArray(n); } int hashCode = 0; for (int i = 0; i < n; i++) { @SuppressWarnings("unchecked") Entry<K, V> entry = entryArray[i]; K key = entry.getKey(); V value = entry.getValue(); checkEntryNotNull(key, value); int keyHash = key.hashCode(); int valueHash = value.hashCode(); int keyBucket = Hashing.smear(keyHash) & mask; int valueBucket = Hashing.smear(valueHash) & mask; ImmutableMapEntry<K, V> nextInKeyBucket = keyTable[keyBucket]; checkNoConflictInKeyBucket(key, entry, nextInKeyBucket); ImmutableMapEntry<K, V> nextInValueBucket = valueTable[valueBucket]; checkNoConflictInValueBucket(value, entry, nextInValueBucket); ImmutableMapEntry<K, V> newEntry; if (nextInValueBucket == null && nextInKeyBucket == null) { /* * TODO(lowasser): consider using a NonTerminalImmutableMapEntry when nextInKeyBucket is * nonnull but nextInValueBucket is null. This may save a few bytes on some platforms, but * 2-morphic call sites are often optimized much better than 3-morphic, so it'd require * benchmarking. */ boolean reusable = entry instanceof ImmutableMapEntry && ((ImmutableMapEntry<K, V>) entry).isReusable(); newEntry = reusable ? (ImmutableMapEntry<K, V>) entry : new ImmutableMapEntry<K, V>(key, value); } else { newEntry = new NonTerminalImmutableBiMapEntry<K, V>( key, value, nextInKeyBucket, nextInValueBucket); } keyTable[keyBucket] = newEntry; valueTable[valueBucket] = newEntry; entries[i] = newEntry; hashCode += keyHash ^ valueHash; } return new RegularImmutableBiMap<K, V>(keyTable, valueTable, entries, mask, hashCode); }
static <K, V> RegularImmutableBiMap<K, V> fromEntryArray(int n, Entry<K, V>[] entryArray) { checkPositionIndex(n, entryArray.length); int tableSize = Hashing.closedTableSize(n, MAX_LOAD_FACTOR); int mask = tableSize - 1; ImmutableMapEntry<K, V>[] keyTable = createEntryArray(tableSize); ImmutableMapEntry<K, V>[] valueTable = createEntryArray(tableSize); Entry<K, V>[] entries; if (n == entryArray.length) { entries = entryArray; } else { entries = createEntryArray(n); } int hashCode = 0; for (int i = 0; i < n; i++) { @SuppressWarnings("unchecked") Entry<K, V> entry = entryArray[i]; K key = entry.getKey(); V value = entry.getValue(); checkEntryNotNull(key, value); int keyHash = key.hashCode(); int valueHash = value.hashCode(); int keyBucket = Hashing.smear(keyHash) & mask; int valueBucket = Hashing.smear(valueHash) & mask; ImmutableMapEntry<K, V> nextInKeyBucket = keyTable[keyBucket]; checkNoConflictInKeyBucket(key, entry, nextInKeyBucket); ImmutableMapEntry<K, V> nextInValueBucket = valueTable[valueBucket]; checkNoConflictInValueBucket(value, entry, nextInValueBucket); ImmutableMapEntry<K, V> newEntry; if (nextInValueBucket == null && nextInKeyBucket == null) { /* * TODO(lowasser): consider using a NonTerminalImmutableMapEntry when nextInKeyBucket is * nonnull but nextInValueBucket is null. This may save a few bytes on some platforms, but * 2-morphic call sites are often optimized much better than 3-morphic, so it'd require * benchmarking. */ boolean reusable = entry instanceof ImmutableMapEntry && ((ImmutableMapEntry<K, V>) entry).isReusable(); newEntry = reusable ? (ImmutableMapEntry<K, V>) entry : new ImmutableMapEntry<K, V>(key, value); } else { newEntry = new NonTerminalImmutableBiMapEntry<K, V>(key, value, nextInKeyBucket, nextInValueBucket); } keyTable[keyBucket] = newEntry; valueTable[valueBucket] = newEntry; entries[i] = newEntry; hashCode += keyHash ^ valueHash; } return new RegularImmutableBiMap<K, V>(keyTable, valueTable, entries, mask, hashCode); }
/** * Constructor for RegularImmutableBiMap that makes no assumptions about the input entries. */ RegularImmutableBiMap(int n, Entry<?, ?>[] entriesToAdd) { checkPositionIndex(n, entriesToAdd.length); int tableSize = Hashing.closedTableSize(n, MAX_LOAD_FACTOR); this.mask = tableSize - 1; ImmutableMapEntry<K, V>[] keyTable = createEntryArray(tableSize); ImmutableMapEntry<K, V>[] valueTable = createEntryArray(tableSize); ImmutableMapEntry<K, V>[] entries = createEntryArray(n); int hashCode = 0; for (int i = 0; i < n; i++) { @SuppressWarnings("unchecked") Entry<K, V> entry = (Entry<K, V>) entriesToAdd[i]; K key = entry.getKey(); V value = entry.getValue(); checkEntryNotNull(key, value); int keyHash = key.hashCode(); int valueHash = value.hashCode(); int keyBucket = Hashing.smear(keyHash) & mask; int valueBucket = Hashing.smear(valueHash) & mask; ImmutableMapEntry<K, V> nextInKeyBucket = keyTable[keyBucket]; checkNoConflictInKeyBucket(key, entry, nextInKeyBucket); ImmutableMapEntry<K, V> nextInValueBucket = valueTable[valueBucket]; checkNoConflictInValueBucket(value, entry, nextInValueBucket); ImmutableMapEntry<K, V> newEntry; if (nextInValueBucket == null && nextInKeyBucket == null) { /* * TODO(user): consider using a NonTerminalImmutableMapEntry when nextInKeyBucket is * nonnull but nextInValueBucket is null. This may save a few bytes on some platforms, but * 2-morphic call sites are often optimized much better than 3-morphic, so it'd require * benchmarking. */ boolean reusable = entry instanceof ImmutableMapEntry && ((ImmutableMapEntry<K, V>) entry).isReusable(); newEntry = reusable ? (ImmutableMapEntry<K, V>) entry : new ImmutableMapEntry<K, V>(key, value); } else { newEntry = new NonTerminalImmutableBiMapEntry<K, V>( key, value, nextInKeyBucket, nextInValueBucket); } keyTable[keyBucket] = newEntry; valueTable[valueBucket] = newEntry; entries[i] = newEntry; hashCode += keyHash ^ valueHash; } this.keyTable = keyTable; this.valueTable = valueTable; this.entries = entries; this.hashCode = hashCode; }
static <K, V> RegularImmutableBiMap<K, V> fromEntryArray(int n, Entry<K, V>[] entryArray) { checkPositionIndex(n, entryArray.length); int tableSize = Hashing.closedTableSize(n, MAX_LOAD_FACTOR); int mask = tableSize - 1; ImmutableMapEntry<K, V>[] keyTable = createEntryArray(tableSize); ImmutableMapEntry<K, V>[] valueTable = createEntryArray(tableSize); Entry<K, V>[] entries; if (n == entryArray.length) { entries = entryArray; } else { entries = createEntryArray(n); } int hashCode = 0; for (int i = 0; i < n; i++) { @SuppressWarnings("unchecked") Entry<K, V> entry = entryArray[i]; K key = entry.getKey(); V value = entry.getValue(); checkEntryNotNull(key, value); int keyHash = key.hashCode(); int valueHash = value.hashCode(); int keyBucket = Hashing.smear(keyHash) & mask; int valueBucket = Hashing.smear(valueHash) & mask; ImmutableMapEntry<K, V> nextInKeyBucket = keyTable[keyBucket]; checkNoConflictInKeyBucket(key, entry, nextInKeyBucket); ImmutableMapEntry<K, V> nextInValueBucket = valueTable[valueBucket]; checkNoConflictInValueBucket(value, entry, nextInValueBucket); ImmutableMapEntry<K, V> newEntry; if (nextInValueBucket == null && nextInKeyBucket == null) { /* * TODO(lowasser): consider using a NonTerminalImmutableMapEntry when nextInKeyBucket is * nonnull but nextInValueBucket is null. This may save a few bytes on some platforms, but * 2-morphic call sites are often optimized much better than 3-morphic, so it'd require * benchmarking. */ boolean reusable = entry instanceof ImmutableMapEntry && ((ImmutableMapEntry<K, V>) entry).isReusable(); newEntry = reusable ? (ImmutableMapEntry<K, V>) entry : new ImmutableMapEntry<K, V>(key, value); } else { newEntry = new NonTerminalImmutableBiMapEntry<>(key, value, nextInKeyBucket, nextInValueBucket); } keyTable[keyBucket] = newEntry; valueTable[valueBucket] = newEntry; entries[i] = newEntry; hashCode += keyHash ^ valueHash; } return new RegularImmutableBiMap<>(keyTable, valueTable, entries, mask, hashCode); }