11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/* 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2008 The Guava Authors 31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); 51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you may not use this file except in compliance with the License. 61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * You may obtain a copy of the License at 71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0 91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software 111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS, 121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * See the License for the specific language governing permissions and 141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License. 151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.collect; 181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.base.Preconditions.checkArgument; 201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtCompatible; 221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.ImmutableSet.ArrayImmutableSet; 231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.ImmutableSet.TransformedImmutableSet; 241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.Nullable; 261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.concurrent.Immutable; 271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/** 291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Implementation of {@link ImmutableMap} with two or more entries. 301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Jesse Wilson 321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Kevin Bourrillion 331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Gregory Kick 341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@GwtCompatible(serializable = true, emulated = true) 361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertfinal class RegularImmutableMap<K, V> extends ImmutableMap<K, V> { 371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // entries in insertion order 391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final transient LinkedEntry<K, V>[] entries; 401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // array of linked lists of entries 411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final transient LinkedEntry<K, V>[] table; 421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // 'and' with an int to get a table index 431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final transient int mask; 441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final transient int keySetHashCode; 451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // TODO(gak): investigate avoiding the creation of ImmutableEntries since we 471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // re-copy them anyway. 481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert RegularImmutableMap(Entry<?, ?>... immutableEntries) { 491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int size = immutableEntries.length; 501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert entries = createEntryArray(size); 511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int tableSize = chooseTableSize(size); 531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert table = createEntryArray(tableSize); 541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert mask = tableSize - 1; 551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int keySetHashCodeMutable = 0; 571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (int entryIndex = 0; entryIndex < size; entryIndex++) { 581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // each of our 6 callers carefully put only Entry<K, V>s into the array! 591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @SuppressWarnings("unchecked") 601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Entry<K, V> entry = (Entry<K, V>) immutableEntries[entryIndex]; 611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert K key = entry.getKey(); 621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int keyHashCode = key.hashCode(); 631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert keySetHashCodeMutable += keyHashCode; 641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int tableIndex = Hashing.smear(keyHashCode) & mask; 651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Nullable LinkedEntry<K, V> existing = table[tableIndex]; 661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // prepend, not append, so the entries can be immutable 671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert LinkedEntry<K, V> linkedEntry = 681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert newLinkedEntry(key, entry.getValue(), existing); 691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert table[tableIndex] = linkedEntry; 701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert entries[entryIndex] = linkedEntry; 711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert while (existing != null) { 721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkArgument(!key.equals(existing.getKey()), "duplicate key: %s", key); 731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert existing = existing.next(); 741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert keySetHashCode = keySetHashCodeMutable; 771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static int chooseTableSize(int size) { 801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // least power of 2 greater than size 811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int tableSize = Integer.highestOneBit(size) << 1; 821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkArgument(tableSize > 0, "table too large: %s", size); 831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return tableSize; 841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Creates a {@link LinkedEntry} array to hold parameterized entries. The 881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * result must never be upcast back to LinkedEntry[] (or Object[], etc.), or 891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * allowed to escape the class. 901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @SuppressWarnings("unchecked") // Safe as long as the javadocs are followed 921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private LinkedEntry<K, V>[] createEntryArray(int size) { 931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new LinkedEntry[size]; 941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static <K, V> LinkedEntry<K, V> newLinkedEntry(K key, V value, 971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Nullable LinkedEntry<K, V> next) { 981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return (next == null) 991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ? new TerminalEntry<K, V>(key, value) 1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert : new NonTerminalEntry<K, V>(key, value, next); 1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private interface LinkedEntry<K, V> extends Entry<K, V> { 1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** Returns the next entry in the list or {@code null} if none exists. */ 1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Nullable LinkedEntry<K, V> next(); 1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** {@code LinkedEntry} implementation that has a next value. */ 1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Immutable 1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @SuppressWarnings("serial") // this class is never serialized 1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final class NonTerminalEntry<K, V> 1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert extends ImmutableEntry<K, V> implements LinkedEntry<K, V> { 1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final LinkedEntry<K, V> next; 1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert NonTerminalEntry(K key, V value, LinkedEntry<K, V> next) { 1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert super(key, value); 1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.next = next; 1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public LinkedEntry<K, V> next() { 1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return next; 1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code LinkedEntry} implementation that serves as the last entry in the 1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * list. I.e. no next entry 1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Immutable 1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @SuppressWarnings("serial") // this class is never serialized 1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final class TerminalEntry<K, V> extends ImmutableEntry<K, V> 1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert implements LinkedEntry<K, V> { 1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert TerminalEntry(K key, V value) { 1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert super(key, value); 1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Nullable @Override public LinkedEntry<K, V> next() { 1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return null; 1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public V get(@Nullable Object key) { 1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (key == null) { 1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return null; 1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int index = Hashing.smear(key.hashCode()) & mask; 1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (LinkedEntry<K, V> entry = table[index]; 1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert entry != null; 1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert entry = entry.next()) { 1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert K candidateKey = entry.getKey(); 1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /* 1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Assume that equals uses the == optimization when appropriate, and that 1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * it would check hash codes as an optimization when appropriate. If we 1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * did these things, it would just make things worse for the most 1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * performance-conscious users. 1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (key.equals(candidateKey)) { 1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return entry.getValue(); 1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return null; 1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public int size() { 1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return entries.length; 1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public boolean isEmpty() { 1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public boolean containsValue(@Nullable Object value) { 1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (value == null) { 1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (Entry<K, V> entry : entries) { 1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (entry.getValue().equals(value)) { 1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return true; 1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override boolean isPartialView() { 1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private transient ImmutableSet<Entry<K, V>> entrySet; 1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public ImmutableSet<Entry<K, V>> entrySet() { 1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ImmutableSet<Entry<K, V>> es = entrySet; 1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return (es == null) ? (entrySet = new EntrySet<K, V>(this)) : es; 1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @SuppressWarnings("serial") // uses writeReplace(), not default serialization 1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static class EntrySet<K, V> extends ArrayImmutableSet<Entry<K, V>> { 1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final transient RegularImmutableMap<K, V> map; 2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert EntrySet(RegularImmutableMap<K, V> map) { 2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert super(map.entries); 2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.map = map; 2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public boolean contains(Object target) { 2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (target instanceof Entry) { 2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Entry<?, ?> entry = (Entry<?, ?>) target; 2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert V mappedValue = map.get(entry.getKey()); 2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return mappedValue != null && mappedValue.equals(entry.getValue()); 2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private transient ImmutableSet<K> keySet; 2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public ImmutableSet<K> keySet() { 2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ImmutableSet<K> ks = keySet; 2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return (ks == null) ? (keySet = new KeySet<K, V>(this)) : ks; 2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @SuppressWarnings("serial") // uses writeReplace(), not default serialization 2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static class KeySet<K, V> 2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert extends TransformedImmutableSet<Entry<K, V>, K> { 2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final RegularImmutableMap<K, V> map; 2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert KeySet(RegularImmutableMap<K, V> map) { 2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert super(map.entries, map.keySetHashCode); 2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.map = map; 2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override K transform(Entry<K, V> element) { 2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return element.getKey(); 2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public boolean contains(Object target) { 2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return map.containsKey(target); 2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override boolean isPartialView() { 2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return true; 2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private transient ImmutableCollection<V> values; 2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public ImmutableCollection<V> values() { 2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ImmutableCollection<V> v = values; 2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return (v == null) ? (values = new Values<V>(this)) : v; 2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @SuppressWarnings("serial") // uses writeReplace(), not default serialization 2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static class Values<V> extends ImmutableCollection<V> { 2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final RegularImmutableMap<?, V> map; 2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Values(RegularImmutableMap<?, V> map) { 2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.map = map; 2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public int size() { 2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return map.entries.length; 2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public UnmodifiableIterator<V> iterator() { 2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new AbstractIndexedListIterator<V>(map.entries.length) { 2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override protected V get(int index) { 2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return map.entries[index].getValue(); 2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public boolean contains(Object target) { 2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return map.containsValue(target); 2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override boolean isPartialView() { 2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return true; 2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override public String toString() { 2841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert StringBuilder result 2851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert = Collections2.newStringBuilderForCollection(size()).append('{'); 2861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Collections2.STANDARD_JOINER.appendTo(result, entries); 2871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return result.append('}').toString(); 2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // This class is never actually serialized directly, but we have to make the 2911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // warning go away (and suppressing would suppress for all nested classes too) 2921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final long serialVersionUID = 0; 2931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 294