Example #1
0
  /** Constructor for RegularImmutableBiMap that makes no assumptions about the input entries. */
  RegularImmutableBiMap(Entry<?, ?>[] entriesToAdd) {
    int 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];
      for (ImmutableMapEntry<K, V> keyEntry = nextInKeyBucket;
          keyEntry != null;
          keyEntry = keyEntry.getNextInKeyBucket()) {
        checkNoConflict(!key.equals(keyEntry.getKey()), "key", entry, keyEntry);
      }
      ImmutableMapEntry<K, V> nextInValueBucket = valueTable[valueBucket];
      for (ImmutableMapEntry<K, V> valueEntry = nextInValueBucket;
          valueEntry != null;
          valueEntry = valueEntry.getNextInValueBucket()) {
        checkNoConflict(!value.equals(valueEntry.getValue()), "value", entry, valueEntry);
      }
      ImmutableMapEntry<K, V> newEntry =
          (nextInKeyBucket == null && nextInValueBucket == null)
              ? new TerminalEntry<K, V>(key, value)
              : new NonTerminalBiMapEntry<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;
  }
 /**
  * Constructor for RegularImmutableMap that takes as input an array of {@code TerminalEntry}
  * entries. Assumes that these entries have already been checked for null.
  *
  * <p>This allows reuse of the entry objects from the array in the actual implementation.
  */
 RegularImmutableMap(int size, TerminalEntry<?, ?>[] theEntries) {
   entries = createEntryArray(size);
   int tableSize = Hashing.closedTableSize(size, MAX_LOAD_FACTOR);
   table = createEntryArray(tableSize);
   mask = tableSize - 1;
   for (int entryIndex = 0; entryIndex < size; entryIndex++) {
     @SuppressWarnings("unchecked")
     TerminalEntry<K, V> entry = (TerminalEntry<K, V>) theEntries[entryIndex];
     K key = entry.getKey();
     int tableIndex = Hashing.smear(key.hashCode()) & mask;
     @Nullable ImmutableMapEntry<K, V> existing = table[tableIndex];
     // prepend, not append, so the entries can be immutable
     ImmutableMapEntry<K, V> newEntry =
         (existing == null) ? entry : new NonTerminalMapEntry<K, V>(entry, existing);
     table[tableIndex] = newEntry;
     entries[entryIndex] = newEntry;
     checkNoConflictInBucket(key, newEntry, existing);
   }
 }
 /** Constructor for RegularImmutableMap that makes no assumptions about the input entries. */
 RegularImmutableMap(Entry<?, ?>[] theEntries) {
   int size = theEntries.length;
   entries = createEntryArray(size);
   int tableSize = Hashing.closedTableSize(size, MAX_LOAD_FACTOR);
   table = createEntryArray(tableSize);
   mask = tableSize - 1;
   for (int entryIndex = 0; entryIndex < size; entryIndex++) {
     @SuppressWarnings("unchecked") // all our callers carefully put in only Entry<K, V>s
     Entry<K, V> entry = (Entry<K, V>) theEntries[entryIndex];
     K key = entry.getKey();
     V value = entry.getValue();
     checkEntryNotNull(key, value);
     int tableIndex = Hashing.smear(key.hashCode()) & mask;
     @Nullable ImmutableMapEntry<K, V> existing = table[tableIndex];
     // prepend, not append, so the entries can be immutable
     ImmutableMapEntry<K, V> newEntry =
         (existing == null)
             ? new TerminalEntry<K, V>(key, value)
             : new NonTerminalMapEntry<K, V>(key, value, existing);
     table[tableIndex] = newEntry;
     entries[entryIndex] = newEntry;
     checkNoConflictInBucket(key, newEntry, existing);
   }
 }