11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/* 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2009 The Guava Authors 31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * in compliance with the License. You may obtain a copy of the License at 61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0 81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software distributed under the License 101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * or implied. See the License for the specific language governing permissions and limitations under 121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the License. 131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.collect; 161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.base.Objects.firstNonNull; 181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.base.Preconditions.checkArgument; 191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.base.Preconditions.checkNotNull; 201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.base.Preconditions.checkState; 211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtCompatible; 231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtIncompatible; 241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Ascii; 251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Equivalence; 261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Equivalences; 271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Function; 281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Objects; 29cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamiltonimport com.google.common.base.Throwables; 301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Ticker; 311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.MapMakerInternalMap.Strength; 321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.io.Serializable; 341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.lang.ref.SoftReference; 351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.lang.ref.WeakReference; 361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.AbstractMap; 371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Collections; 381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.ConcurrentModificationException; 391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Map; 401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Set; 411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ConcurrentHashMap; 421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ConcurrentMap; 43cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamiltonimport java.util.concurrent.ExecutionException; 441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.TimeUnit; 451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.Nullable; 471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/** 491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>A builder of {@link ConcurrentMap} instances having any combination of the following features: 501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <ul> 521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li>keys or values automatically wrapped in {@linkplain WeakReference weak} or {@linkplain 531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * SoftReference soft} references 541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li>least-recently-used eviction when a maximum size is exceeded 551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li>time-based expiration of entries, measured since last access or last write 561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li>notification of evicted (or otherwise removed) entries 571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li>on-demand computation of values for keys not already present 581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * </ul> 591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>Usage example: <pre> {@code 611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * ConcurrentMap<Key, Graph> graphs = new MapMaker() 631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * .concurrencyLevel(4) 641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * .weakKeys() 651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * .maximumSize(10000) 661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * .expireAfterWrite(10, TimeUnit.MINUTES) 671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * .makeComputingMap( 681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * new Function<Key, Graph>() { 691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * public Graph apply(Key key) { 701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * return createExpensiveGraph(key); 711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * } 721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * });}</pre> 731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * These features are all optional; {@code new MapMaker().makeMap()} returns a valid concurrent map 751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * that behaves similarly to a {@link ConcurrentHashMap}. 761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>The returned map is implemented as a hash table with similar performance characteristics to 781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link ConcurrentHashMap}. It supports all optional operations of the {@code ConcurrentMap} 791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * interface. It does not permit null keys or values. 801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p><b>Note:</b> by default, the returned map uses equality comparisons (the {@link Object#equals 821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * equals} method) to determine equality for keys or values. However, if {@link #weakKeys} or {@link 831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * #softKeys} was specified, the map uses identity ({@code ==}) comparisons instead for keys. 841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Likewise, if {@link #weakValues} or {@link #softValues} was specified, the map uses identity 851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * comparisons for values. 861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>The view collections of the returned map have <i>weakly consistent iterators</i>. This means 881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * that they are safe for concurrent use, but if other threads modify the map after the iterator is 891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * created, it is undefined which of these changes, if any, are reflected in that iterator. These 901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * iterators never throw {@link ConcurrentModificationException}. 911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>If soft or weak references were requested, it is possible for a key or value present in the 931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the map to be reclaimed by the garbage collector. If this happens, the entry automatically 941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * disappears from the map. A partially-reclaimed entry is never exposed to the user. Any {@link 951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * java.util.Map.Entry} instance retrieved from the map's {@linkplain Map#entrySet entry set} is a 961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * snapshot of that entry's state at the time of retrieval; such entries do, however, support {@link 971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * java.util.Map.Entry#setValue}, which simply calls {@link Map#put} on the entry's key. 981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>The maps produced by {@code MapMaker} are serializable, and the deserialized maps retain all 1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the configuration properties of the original map. During deserialization, if the original map had 1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * used soft or weak references, the entries are reconstructed as they were, but it's not unlikely 1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * they'll be quickly garbage-collected before they are ever accessed. 1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>{@code new MapMaker().weakKeys().makeMap()} is a recommended replacement for {@link 1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * java.util.WeakHashMap}, but note that it compares keys using object identity whereas {@code 1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WeakHashMap} uses {@link Object#equals}. 1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Bob Lee 1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Charles Fry 1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Kevin Bourrillion 1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 2.0 (imported from Google Collections Library) 1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@GwtCompatible(emulated = true) 1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic final class MapMaker extends GenericMapMaker<Object, Object> { 1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final int DEFAULT_INITIAL_CAPACITY = 16; 1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final int DEFAULT_CONCURRENCY_LEVEL = 4; 1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final int DEFAULT_EXPIRATION_NANOS = 0; 1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert static final int UNSET_INT = -1; 1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // TODO(kevinb): dispense with this after benchmarking 1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert boolean useCustomMap; 1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int initialCapacity = UNSET_INT; 1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int concurrencyLevel = UNSET_INT; 1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int maximumSize = UNSET_INT; 1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Strength keyStrength; 1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Strength valueStrength; 1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert long expireAfterWriteNanos = UNSET_INT; 1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert long expireAfterAccessNanos = UNSET_INT; 1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert RemovalCause nullRemovalCause; 1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Equivalence<Object> keyEquivalence; 1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Equivalence<Object> valueEquivalence; 1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Ticker ticker; 1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Constructs a new {@code MapMaker} instance with default settings, including strong keys, strong 1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * values, and no automatic eviction of any kind. 1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public MapMaker() {} 1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private boolean useNullMap() { 1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return (nullRemovalCause == null); 1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Sets a custom {@code Equivalence} strategy for comparing keys. 1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>By default, the map uses {@link Equivalences#identity} to determine key equality when 1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link #weakKeys} or {@link #softKeys} is specified, and {@link Equivalences#equals()} 1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * otherwise. 1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @GwtIncompatible("To be supported") 1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MapMaker keyEquivalence(Equivalence<Object> equivalence) { 1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkState(keyEquivalence == null, "key equivalence was already set to %s", keyEquivalence); 1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert keyEquivalence = checkNotNull(equivalence); 1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.useCustomMap = true; 1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return this; 1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Equivalence<Object> getKeyEquivalence() { 1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return firstNonNull(keyEquivalence, getKeyStrength().defaultEquivalence()); 1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Sets a custom {@code Equivalence} strategy for comparing values. 1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>By default, the map uses {@link Equivalences#identity} to determine value equality when 1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link #weakValues} or {@link #softValues} is specified, and {@link Equivalences#equals()} 1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * otherwise. 1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @GwtIncompatible("To be supported") 1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MapMaker valueEquivalence(Equivalence<Object> equivalence) { 1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkState(valueEquivalence == null, 1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert "value equivalence was already set to %s", valueEquivalence); 1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.valueEquivalence = checkNotNull(equivalence); 1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.useCustomMap = true; 1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return this; 1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Equivalence<Object> getValueEquivalence() { 1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return firstNonNull(valueEquivalence, getValueStrength().defaultEquivalence()); 1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Sets the minimum total size for the internal hash tables. For example, if the initial capacity 1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * is {@code 60}, and the concurrency level is {@code 8}, then eight segments are created, each 1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * having a hash table of size eight. Providing a large enough estimate at construction time 1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * avoids the need for expensive resizing operations later, but setting this value unnecessarily 1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * high wastes memory. 1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws IllegalArgumentException if {@code initialCapacity} is negative 2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws IllegalStateException if an initial capacity was already set 2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public MapMaker initialCapacity(int initialCapacity) { 2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkState(this.initialCapacity == UNSET_INT, "initial capacity was already set to %s", 2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.initialCapacity); 2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkArgument(initialCapacity >= 0); 2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.initialCapacity = initialCapacity; 2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return this; 2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int getInitialCapacity() { 2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return (initialCapacity == UNSET_INT) ? DEFAULT_INITIAL_CAPACITY : initialCapacity; 2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Specifies the maximum number of entries the map may contain. Note that the map <b>may evict an 2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * entry before this limit is exceeded</b>. As the map size grows close to the maximum, the map 2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * evicts entries that are less likely to be used again. For example, the map may evict an entry 2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * because it hasn't been used recently or very often. 2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>When {@code size} is zero, elements can be successfully added to the map, but are evicted 2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * immediately. This has the same effect as invoking {@link #expireAfterWrite 2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * expireAfterWrite}{@code (0, unit)} or {@link #expireAfterAccess expireAfterAccess}{@code (0, 2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * unit)}. It can be useful in testing, or to disable caching temporarily without a code change. 2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>Caching functionality in {@code MapMaker} is being moved to 2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link com.google.common.cache.CacheBuilder}. 2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param size the maximum size of the map 2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws IllegalArgumentException if {@code size} is negative 2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws IllegalStateException if a maximum size was already set 2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @deprecated Caching functionality in {@code MapMaker} is being moved to 2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link com.google.common.cache.CacheBuilder}, with {@link #maximumSize} being 2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * replaced by {@link com.google.common.cache.CacheBuilder#maximumSize}. 2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Deprecated 2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MapMaker maximumSize(int size) { 2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkState(this.maximumSize == UNSET_INT, "maximum size was already set to %s", 2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.maximumSize); 2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkArgument(size >= 0, "maximum size must not be negative"); 2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.maximumSize = size; 2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.useCustomMap = true; 2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (maximumSize == 0) { 2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // SIZE trumps EXPIRED 2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.nullRemovalCause = RemovalCause.SIZE; 2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return this; 2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Guides the allowed concurrency among update operations. Used as a hint for internal sizing. The 2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * table is internally partitioned to try to permit the indicated number of concurrent updates 2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * without contention. Because assignment of entries to these partitions is not necessarily 2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * uniform, the actual concurrency observed may vary. Ideally, you should choose a value to 2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * accommodate as many threads as will ever concurrently modify the table. Using a significantly 2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * higher value than you need can waste space and time, and a significantly lower value can lead 2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * to thread contention. But overestimates and underestimates within an order of magnitude do not 2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * usually have much noticeable impact. A value of one permits only one thread to modify the map 2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * at a time, but since read operations can proceed concurrently, this still yields higher 2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * concurrency than full synchronization. Defaults to 4. 2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p><b>Note:</b> Prior to Guava release 9.0, the default was 16. It is possible the default will 2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * change again in the future. If you care about this value, you should always choose it 2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * explicitly. 2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws IllegalArgumentException if {@code concurrencyLevel} is nonpositive 2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws IllegalStateException if a concurrency level was already set 2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public MapMaker concurrencyLevel(int concurrencyLevel) { 2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkState(this.concurrencyLevel == UNSET_INT, "concurrency level was already set to %s", 2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.concurrencyLevel); 2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkArgument(concurrencyLevel > 0); 2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.concurrencyLevel = concurrencyLevel; 2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return this; 2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int getConcurrencyLevel() { 2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return (concurrencyLevel == UNSET_INT) ? DEFAULT_CONCURRENCY_LEVEL : concurrencyLevel; 2811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 2841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Specifies that each key (not value) stored in the map should be strongly referenced. 2851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 2861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws IllegalStateException if the key strength was already set 2871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 2891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MapMaker strongKeys() { 2901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return setKeyStrength(Strength.STRONG); 2911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 2941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Specifies that each key (not value) stored in the map should be wrapped in a {@link 2951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WeakReference} (by default, strong references are used). 2961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 2971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p><b>Warning:</b> when this method is used, the resulting map will use identity ({@code ==}) 2981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * comparison to determine equality of keys, which is a technical violation of the {@link Map} 2991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * specification, and may not be what you expect. 3001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 3011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws IllegalStateException if the key strength was already set 3021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @see WeakReference 3031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 3041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @GwtIncompatible("java.lang.ref.WeakReference") 3051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 3061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public MapMaker weakKeys() { 3071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return setKeyStrength(Strength.WEAK); 3081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 3111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <b>This method is broken.</b> Maps with soft keys offer no functional advantage over maps with 3121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * weak keys, and they waste memory by keeping unreachable elements in the map. If your goal is to 3131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * create a memory-sensitive map, then consider using soft values instead. 3141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 3151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>Specifies that each key (not value) stored in the map should be wrapped in a 3161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link SoftReference} (by default, strong references are used). Softly-referenced objects will 3171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * be garbage-collected in a <i>globally</i> least-recently-used manner, in response to memory 3181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * demand. 3191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 3201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p><b>Warning:</b> when this method is used, the resulting map will use identity ({@code ==}) 3211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * comparison to determine equality of keys, which is a technical violation of the {@link Map} 3221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * specification, and may not be what you expect. 3231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 3241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws IllegalStateException if the key strength was already set 3251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @see SoftReference 3261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @deprecated use {@link #softValues} to create a memory-sensitive map, or {@link #weakKeys} to 3271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * create a map that doesn't hold strong references to the keys. 3281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <b>This method is scheduled for deletion in January 2013.</b> 3291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 3301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Deprecated 3311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @GwtIncompatible("java.lang.ref.SoftReference") 3321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 3331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public MapMaker softKeys() { 3341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return setKeyStrength(Strength.SOFT); 3351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MapMaker setKeyStrength(Strength strength) { 3381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkState(keyStrength == null, "Key strength was already set to %s", keyStrength); 3391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert keyStrength = checkNotNull(strength); 3401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (strength != Strength.STRONG) { 3411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // STRONG could be used during deserialization. 3421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert useCustomMap = true; 3431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return this; 3451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Strength getKeyStrength() { 3481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return firstNonNull(keyStrength, Strength.STRONG); 3491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 3521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Specifies that each value (not key) stored in the map should be strongly referenced. 3531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 3541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws IllegalStateException if the value strength was already set 3551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 3561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 3571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MapMaker strongValues() { 3581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return setValueStrength(Strength.STRONG); 3591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 3621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Specifies that each value (not key) stored in the map should be wrapped in a 3631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link WeakReference} (by default, strong references are used). 3641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 3651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>Weak values will be garbage collected once they are weakly reachable. This makes them a poor 3661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * candidate for caching; consider {@link #softValues} instead. 3671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 3681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p><b>Warning:</b> when this method is used, the resulting map will use identity ({@code ==}) 3691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * comparison to determine equality of values. This technically violates the specifications of 3701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the methods {@link Map#containsValue containsValue}, 3711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link ConcurrentMap#remove(Object, Object) remove(Object, Object)} and 3721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link ConcurrentMap#replace(Object, Object, Object) replace(K, V, V)}, and may not be what you 3731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * expect. 3741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 3751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws IllegalStateException if the value strength was already set 3761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @see WeakReference 3771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 3781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @GwtIncompatible("java.lang.ref.WeakReference") 3791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 3801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public MapMaker weakValues() { 3811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return setValueStrength(Strength.WEAK); 3821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 3851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Specifies that each value (not key) stored in the map should be wrapped in a 3861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link SoftReference} (by default, strong references are used). Softly-referenced objects will 3871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * be garbage-collected in a <i>globally</i> least-recently-used manner, in response to memory 3881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * demand. 3891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 3901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p><b>Warning:</b> in most circumstances it is better to set a per-cache {@linkplain 3911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * #maximumSize maximum size} instead of using soft references. You should only use this method if 3921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you are well familiar with the practical consequences of soft references. 3931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 3941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p><b>Warning:</b> when this method is used, the resulting map will use identity ({@code ==}) 3951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * comparison to determine equality of values. This technically violates the specifications of 3961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the methods {@link Map#containsValue containsValue}, 3971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link ConcurrentMap#remove(Object, Object) remove(Object, Object)} and 3981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link ConcurrentMap#replace(Object, Object, Object) replace(K, V, V)}, and may not be what you 3991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * expect. 4001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 4011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws IllegalStateException if the value strength was already set 4021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @see SoftReference 4031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 4041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @GwtIncompatible("java.lang.ref.SoftReference") 4051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 4061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public MapMaker softValues() { 4071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return setValueStrength(Strength.SOFT); 4081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MapMaker setValueStrength(Strength strength) { 4111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkState(valueStrength == null, "Value strength was already set to %s", valueStrength); 4121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert valueStrength = checkNotNull(strength); 4131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (strength != Strength.STRONG) { 4141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // STRONG could be used during deserialization. 4151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert useCustomMap = true; 4161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return this; 4181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Strength getValueStrength() { 4211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return firstNonNull(valueStrength, Strength.STRONG); 4221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 4251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Old name of {@link #expireAfterWrite}. 4261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 4271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @deprecated Caching functionality in {@code MapMaker} is being moved to 4281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link com.google.common.cache.CacheBuilder}. Functionality equivalent to 4291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link MapMaker#expiration} is provided by 4301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link com.google.common.cache.CacheBuilder#expireAfterWrite}. 4311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <b>This method is scheduled for deletion in July 2012.</b> 4321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 4331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Deprecated 4341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 4351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public 4361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MapMaker expiration(long duration, TimeUnit unit) { 4371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return expireAfterWrite(duration, unit); 4381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 4411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Specifies that each entry should be automatically removed from the map once a fixed duration 4421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * has elapsed after the entry's creation, or the most recent replacement of its value. 4431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 4441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>When {@code duration} is zero, elements can be successfully added to the map, but are 4451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * evicted immediately. This has a very similar effect to invoking {@link #maximumSize 4461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * maximumSize}{@code (0)}. It can be useful in testing, or to disable caching temporarily without 4471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * a code change. 4481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 4491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>Expired entries may be counted by {@link Map#size}, but will never be visible to read or 4501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * write operations. Expired entries are currently cleaned up during write operations, or during 4511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * occasional read operations in the absense of writes; though this behavior may change in the 4521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * future. 4531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 4541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param duration the length of time after an entry is created that it should be automatically 4551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * removed 4561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param unit the unit that {@code duration} is expressed in 4571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws IllegalArgumentException if {@code duration} is negative 4581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws IllegalStateException if the time to live or time to idle was already set 4591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @deprecated Caching functionality in {@code MapMaker} is being moved to 4601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link com.google.common.cache.CacheBuilder}, with {@link #expireAfterWrite} being 4611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * replaced by {@link com.google.common.cache.CacheBuilder#expireAfterWrite}. 4621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 4631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Deprecated 4641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 4651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MapMaker expireAfterWrite(long duration, TimeUnit unit) { 4661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkExpiration(duration, unit); 4671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.expireAfterWriteNanos = unit.toNanos(duration); 4681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (duration == 0 && this.nullRemovalCause == null) { 4691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // SIZE trumps EXPIRED 4701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.nullRemovalCause = RemovalCause.EXPIRED; 4711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert useCustomMap = true; 4731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return this; 4741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private void checkExpiration(long duration, TimeUnit unit) { 4771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkState(expireAfterWriteNanos == UNSET_INT, "expireAfterWrite was already set to %s ns", 4781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expireAfterWriteNanos); 4791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkState(expireAfterAccessNanos == UNSET_INT, "expireAfterAccess was already set to %s ns", 4801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert expireAfterAccessNanos); 4811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkArgument(duration >= 0, "duration cannot be negative: %s %s", duration, unit); 4821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert long getExpireAfterWriteNanos() { 4851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return (expireAfterWriteNanos == UNSET_INT) ? DEFAULT_EXPIRATION_NANOS : expireAfterWriteNanos; 4861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 4871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 4881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 4891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Specifies that each entry should be automatically removed from the map once a fixed duration 4901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * has elapsed after the entry's last read or write access. 4911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 4921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>When {@code duration} is zero, elements can be successfully added to the map, but are 4931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * evicted immediately. This has a very similar effect to invoking {@link #maximumSize 4941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * maximumSize}{@code (0)}. It can be useful in testing, or to disable caching temporarily without 4951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * a code change. 4961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 4971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>Expired entries may be counted by {@link Map#size}, but will never be visible to read or 4981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * write operations. Expired entries are currently cleaned up during write operations, or during 4991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * occasional read operations in the absense of writes; though this behavior may change in the 5001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * future. 5011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 5021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param duration the length of time after an entry is last accessed that it should be 5031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * automatically removed 5041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param unit the unit that {@code duration} is expressed in 5051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws IllegalArgumentException if {@code duration} is negative 5061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws IllegalStateException if the time to idle or time to live was already set 5071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @deprecated Caching functionality in {@code MapMaker} is being moved to 5081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link com.google.common.cache.CacheBuilder}, with {@link #expireAfterAccess} being 5091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * replaced by {@link com.google.common.cache.CacheBuilder#expireAfterAccess}. 5101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 5111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Deprecated 5121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @GwtIncompatible("To be supported") 5131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 5141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MapMaker expireAfterAccess(long duration, TimeUnit unit) { 5151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkExpiration(duration, unit); 5161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.expireAfterAccessNanos = unit.toNanos(duration); 5171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (duration == 0 && this.nullRemovalCause == null) { 5181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // SIZE trumps EXPIRED 5191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.nullRemovalCause = RemovalCause.EXPIRED; 5201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert useCustomMap = true; 5221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return this; 5231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert long getExpireAfterAccessNanos() { 5261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return (expireAfterAccessNanos == UNSET_INT) 5271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ? DEFAULT_EXPIRATION_NANOS : expireAfterAccessNanos; 5281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Ticker getTicker() { 5311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return firstNonNull(ticker, Ticker.systemTicker()); 5321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 5351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Specifies a listener instance, which all maps built using this {@code MapMaker} will notify 5361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * each time an entry is removed from the map by any means. 5371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 5381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>Each map built by this map maker after this method is called invokes the supplied listener 5391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * after removing an element for any reason (see removal causes in {@link RemovalCause}). It will 5401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * invoke the listener during invocations of any of that map's public methods (even read-only 5411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * methods). 5421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 5431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p><b>Important note:</b> Instead of returning <i>this</i> as a {@code MapMaker} instance, 5441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * this method returns {@code GenericMapMaker<K, V>}. From this point on, either the original 5451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * reference or the returned reference may be used to complete configuration and build the map, 5461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * but only the "generic" one is type-safe. That is, it will properly prevent you from building 5471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * maps whose key or value types are incompatible with the types accepted by the listener already 5481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * provided; the {@code MapMaker} type cannot do this. For best results, simply use the standard 5491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * method-chaining idiom, as illustrated in the documentation at top, configuring a {@code 5501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * MapMaker} and building your {@link Map} all in a single statement. 5511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 5521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p><b>Warning:</b> if you ignore the above advice, and use this {@code MapMaker} to build a map 5531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * or cache whose key or value type is incompatible with the listener, you will likely experience 5541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * a {@link ClassCastException} at some <i>undefined</i> point in the future. 5551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 5561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @throws IllegalStateException if a removal listener was already set 5571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @deprecated Caching functionality in {@code MapMaker} is being moved to 5581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link com.google.common.cache.CacheBuilder}, with {@link #removalListener} being 5591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * replaced by {@link com.google.common.cache.CacheBuilder#removalListener}. 5601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 5611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Deprecated 5621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @GwtIncompatible("To be supported") 5631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert <K, V> GenericMapMaker<K, V> removalListener(RemovalListener<K, V> listener) { 5641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkState(this.removalListener == null); 5651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // safely limiting the kinds of maps this can produce 5671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @SuppressWarnings("unchecked") 5681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert GenericMapMaker<K, V> me = (GenericMapMaker<K, V>) this; 5691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert me.removalListener = checkNotNull(listener); 5701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert useCustomMap = true; 5711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return me; 5721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 5751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Builds a thread-safe map, without on-demand computation of values. This method does not alter 5761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the state of this {@code MapMaker} instance, so it can be invoked again to create multiple 5771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * independent maps. 5781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 5791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>The bulk operations {@code putAll}, {@code equals}, and {@code clear} are not guaranteed to 5801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * be performed atomically on the returned map. Additionally, {@code size} and {@code 5811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * containsValue} are implemented as bulk read operations, and thus may fail to observe concurrent 5821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * writes. 5831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 5841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @return a serializable concurrent map having the requested features 5851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 5861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 5871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public <K, V> ConcurrentMap<K, V> makeMap() { 5881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (!useCustomMap) { 5891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new ConcurrentHashMap<K, V>(getInitialCapacity(), 0.75f, getConcurrencyLevel()); 5901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return (nullRemovalCause == null) 5921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ? new MapMakerInternalMap<K, V>(this) 5931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert : new NullConcurrentMap<K, V>(this); 5941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 5951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 5961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 5971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns a MapMakerInternalMap for the benefit of internal callers that use features of 5981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * that class not exposed through ConcurrentMap. 5991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 6001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 6011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @GwtIncompatible("MapMakerInternalMap") 6021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert <K, V> MapMakerInternalMap<K, V> makeCustomMap() { 6031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return new MapMakerInternalMap<K, V>(this); 6041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 6051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 6061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 6071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Builds a map that supports atomic, on-demand computation of values. {@link Map#get} either 6081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * returns an already-computed value for the given key, atomically computes it using the supplied 6091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * function, or, if another thread is currently computing the value for this key, simply waits for 6101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * that thread to finish and returns its computed value. Note that the function may be executed 6111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * concurrently by multiple threads, but only for distinct keys. 6121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 6131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>New code should use {@link com.google.common.cache.CacheBuilder}, which supports 6141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@linkplain com.google.common.cache.CacheStats statistics} collection, introduces the 6151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link com.google.common.cache.CacheLoader} interface for loading entries into the cache 6161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * (allowing checked exceptions to be thrown in the process), and more cleanly separates 6171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * computation from the cache's {@code Map} view. 6181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 6191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>If an entry's value has not finished computing yet, query methods besides {@code get} return 6201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * immediately as if an entry doesn't exist. In other words, an entry isn't externally visible 6211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * until the value's computation completes. 6221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 6231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>{@link Map#get} on the returned map will never return {@code null}. It may throw: 6241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 6251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <ul> 6261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li>{@link NullPointerException} if the key is null or the computing function returns a null 6271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * result 6281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li>{@link ComputationException} if an exception was thrown by the computing function. If that 6291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * exception is already of type {@link ComputationException} it is propagated directly; otherwise 6301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * it is wrapped. 6311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * </ul> 6321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 6331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p><b>Note:</b> Callers of {@code get} <i>must</i> ensure that the key argument is of type 6341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code K}. The {@code get} method accepts {@code Object}, so the key type is not checked at 6351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * compile time. Passing an object of a type other than {@code K} can result in that object being 6361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * unsafely passed to the computing function as type {@code K}, and unsafely stored in the map. 6371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 6381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>If {@link Map#put} is called before a computation completes, other threads waiting on the 6391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * computation will wake up and return the stored value. 6401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 6411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>This method does not alter the state of this {@code MapMaker} instance, so it can be invoked 6421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * again to create multiple independent maps. 6431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 6441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>Insertion, removal, update, and access operations on the returned map safely execute 6451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * concurrently by multiple threads. Iterators on the returned map are weakly consistent, 6461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * returning elements reflecting the state of the map at some point at or since the creation of 6471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the iterator. They do not throw {@link ConcurrentModificationException}, and may proceed 6481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * concurrently with other operations. 6491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 6501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>The bulk operations {@code putAll}, {@code equals}, and {@code clear} are not guaranteed to 6511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * be performed atomically on the returned map. Additionally, {@code size} and {@code 6521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * containsValue} are implemented as bulk read operations, and thus may fail to observe concurrent 6531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * writes. 6541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 6551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param computingFunction the function used to compute new values 6561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @return a serializable concurrent map having the requested features 6571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @deprecated Caching functionality in {@code MapMaker} is being moved to 6581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link com.google.common.cache.CacheBuilder}, with {@link #makeComputingMap} being replaced 6591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * by {@link com.google.common.cache.CacheBuilder#build}. Note that uses of 6601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link #makeComputingMap} with {@code AtomicLong} values can often be migrated to 6611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link AtomicLongMap}. 6621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <b>This method is scheduled for deletion in February 2013.</b> 6631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 6641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 6651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Deprecated 6661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 6671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public <K, V> ConcurrentMap<K, V> makeComputingMap( 6681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Function<? super K, ? extends V> computingFunction) { 6691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return useNullMap() 670cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton ? new MapMaker.ComputingMapAdapter<K, V>(this, computingFunction) 6711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert : new NullComputingConcurrentMap<K, V>(this, computingFunction); 6721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 6731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 6741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 6751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns a string representation for this MapMaker instance. The exact form of the returned 6761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * string is not specificed. 6771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 6781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 6791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public String toString() { 6801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Objects.ToStringHelper s = Objects.toStringHelper(this); 6811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (initialCapacity != UNSET_INT) { 6821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert s.add("initialCapacity", initialCapacity); 6831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 6841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (concurrencyLevel != UNSET_INT) { 6851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert s.add("concurrencyLevel", concurrencyLevel); 6861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 6871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (maximumSize != UNSET_INT) { 6881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert s.add("maximumSize", maximumSize); 6891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 6901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (expireAfterWriteNanos != UNSET_INT) { 6911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert s.add("expireAfterWrite", expireAfterWriteNanos + "ns"); 6921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 6931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (expireAfterAccessNanos != UNSET_INT) { 6941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert s.add("expireAfterAccess", expireAfterAccessNanos + "ns"); 6951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 6961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (keyStrength != null) { 6971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert s.add("keyStrength", Ascii.toLowerCase(keyStrength.toString())); 6981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 6991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (valueStrength != null) { 7001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert s.add("valueStrength", Ascii.toLowerCase(valueStrength.toString())); 7011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 7021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (keyEquivalence != null) { 7031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert s.addValue("keyEquivalence"); 7041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 7051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (valueEquivalence != null) { 7061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert s.addValue("valueEquivalence"); 7071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 7081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (removalListener != null) { 7091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert s.addValue("removalListener"); 7101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 7111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return s.toString(); 7121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 7131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 7141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 7151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * An object that can receive a notification when an entry is removed from a map. The removal 7161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * resulting in notification could have occured to an entry being manually removed or replaced, or 7171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * due to eviction resulting from timed expiration, exceeding a maximum size, or garbage 7181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * collection. 7191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 7201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>An instance may be called concurrently by multiple threads to process different entries. 7211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Implementations of this interface should avoid performing blocking calls or synchronizing on 7221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * shared resources. 7231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 7241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param <K> the most general type of keys this listener can listen for; for 7251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * example {@code Object} if any key is acceptable 7261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param <V> the most general type of values this listener can listen for; for 7271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * example {@code Object} if any key is acceptable 7281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 7291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert interface RemovalListener<K, V> { 7301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 7311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Notifies the listener that a removal occurred at some point in the past. 7321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 7331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert void onRemoval(RemovalNotification<K, V> notification); 7341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 7351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 7361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 7371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * A notification of the removal of a single entry. The key or value may be null if it was already 7381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * garbage collected. 7391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 7401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>Like other {@code Map.Entry} instances associated with MapMaker, this class holds strong 7411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * references to the key and value, regardless of the type of references the map may be using. 7421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 7431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert static final class RemovalNotification<K, V> extends ImmutableEntry<K, V> { 7441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final long serialVersionUID = 0; 7451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 7461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final RemovalCause cause; 7471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 7481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert RemovalNotification(@Nullable K key, @Nullable V value, RemovalCause cause) { 7491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert super(key, value); 7501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.cause = cause; 7511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 7521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 7531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 7541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns the cause for which the entry was removed. 7551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 7561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public RemovalCause getCause() { 7571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return cause; 7581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 7591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 7601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 7611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns {@code true} if there was an automatic removal due to eviction (the cause is neither 7621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link RemovalCause#EXPLICIT} nor {@link RemovalCause#REPLACED}). 7631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 7641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public boolean wasEvicted() { 7651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return cause.wasEvicted(); 7661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 7671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 7681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 7691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 7701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * The reason why an entry was removed. 7711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 7721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert enum RemovalCause { 7731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 7741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * The entry was manually removed by the user. This can result from the user invoking 7751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link Map#remove}, {@link ConcurrentMap#remove}, or {@link java.util.Iterator#remove}. 7761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 7771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert EXPLICIT { 7781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 7791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert boolean wasEvicted() { 7801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 7811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 7821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }, 7831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 7841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 7851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * The entry itself was not actually removed, but its value was replaced by the user. This can 7861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * result from the user invoking {@link Map#put}, {@link Map#putAll}, 7871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link ConcurrentMap#replace(Object, Object)}, or 7881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link ConcurrentMap#replace(Object, Object, Object)}. 7891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 7901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert REPLACED { 7911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 7921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert boolean wasEvicted() { 7931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 7941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 7951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }, 7961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 7971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 7981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * The entry was removed automatically because its key or value was garbage-collected. This 7991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * can occur when using {@link #softKeys}, {@link #softValues}, {@link #weakKeys}, or {@link 8001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * #weakValues}. 8011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 8021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert COLLECTED { 8031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 8041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert boolean wasEvicted() { 8051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return true; 8061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 8071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }, 8081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 8091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 8101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * The entry's expiration timestamp has passed. This can occur when using {@link 8111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * #expireAfterWrite} or {@link #expireAfterAccess}. 8121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 8131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert EXPIRED { 8141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 8151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert boolean wasEvicted() { 8161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return true; 8171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 8181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }, 8191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 8201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 8211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * The entry was evicted due to size constraints. This can occur when using {@link 8221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * #maximumSize}. 8231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 8241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert SIZE { 8251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 8261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert boolean wasEvicted() { 8271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return true; 8281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 8291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert }; 8301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 8311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 8321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Returns {@code true} if there was an automatic removal due to eviction (the cause is neither 8331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link #EXPLICIT} nor {@link #REPLACED}). 8341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 8351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert abstract boolean wasEvicted(); 8361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 8371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 8381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** A map that is always empty and evicts on insertion. */ 8391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert static class NullConcurrentMap<K, V> extends AbstractMap<K, V> 8401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert implements ConcurrentMap<K, V>, Serializable { 8411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final long serialVersionUID = 0; 8421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 8431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final RemovalListener<K, V> removalListener; 8441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private final RemovalCause removalCause; 8451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 8461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert NullConcurrentMap(MapMaker mapMaker) { 8471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert removalListener = mapMaker.getRemovalListener(); 8481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert removalCause = mapMaker.nullRemovalCause; 8491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 8501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 8511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // implements ConcurrentMap 8521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 8531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 8541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public boolean containsKey(@Nullable Object key) { 8551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 8561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 8571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 8581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 8591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public boolean containsValue(@Nullable Object value) { 8601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 8611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 8621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 8631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 8641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public V get(@Nullable Object key) { 8651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return null; 8661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 8671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 8681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert void notifyRemoval(K key, V value) { 8691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert RemovalNotification<K, V> notification = 8701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert new RemovalNotification<K, V>(key, value, removalCause); 8711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert removalListener.onRemoval(notification); 8721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 8731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 8741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 8751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public V put(K key, V value) { 8761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkNotNull(key); 8771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkNotNull(value); 8781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert notifyRemoval(key, value); 8791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return null; 8801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 8811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 8821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 8831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public V putIfAbsent(K key, V value) { 8841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return put(key, value); 8851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 8861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 8871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 8881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public V remove(@Nullable Object key) { 8891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return null; 8901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 8911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 8921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 8931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public boolean remove(@Nullable Object key, @Nullable Object value) { 8941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 8951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 8961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 8971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 8981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public V replace(K key, V value) { 8991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkNotNull(key); 9001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkNotNull(value); 9011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return null; 9021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 9031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 9041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 9051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public boolean replace(K key, @Nullable V oldValue, V newValue) { 9061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkNotNull(key); 9071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkNotNull(newValue); 9081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 9091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 9101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 9111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 9121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public Set<Entry<K, V>> entrySet() { 9131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return Collections.emptySet(); 9141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 9151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 9161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 9171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** Computes on retrieval and evicts the result. */ 9181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert static final class NullComputingConcurrentMap<K, V> extends NullConcurrentMap<K, V> { 9191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final long serialVersionUID = 0; 9201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 9211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final Function<? super K, ? extends V> computingFunction; 9221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 9231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert NullComputingConcurrentMap( 9241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert MapMaker mapMaker, Function<? super K, ? extends V> computingFunction) { 9251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert super(mapMaker); 9261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.computingFunction = checkNotNull(computingFunction); 9271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 9281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 9291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @SuppressWarnings("unchecked") // unsafe, which is why Cache is preferred 9301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @Override 9311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public V get(Object k) { 9321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert K key = (K) k; 9331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert V value = compute(key); 9341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkNotNull(value, computingFunction + " returned null for key " + key + "."); 9351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert notifyRemoval(key, value); 9361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return value; 9371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 9381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 9391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private V compute(K key) { 9401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkNotNull(key); 9411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 9421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return computingFunction.apply(key); 9431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (ComputationException e) { 9441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw e; 9451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (Throwable t) { 9461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new ComputationException(t); 9471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 9481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 9491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 9501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 951cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton /** 952cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton * Overrides get() to compute on demand. Also throws an exception when {@code null} is returned 953cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton * from a computation. 954cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton */ 955cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton static final class ComputingMapAdapter<K, V> 956cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton extends ComputingConcurrentHashMap<K, V> implements Serializable { 957cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton private static final long serialVersionUID = 0; 958cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton 959cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton ComputingMapAdapter(MapMaker mapMaker, 960cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton Function<? super K, ? extends V> computingFunction) { 961cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton super(mapMaker, computingFunction); 962cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton } 963cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton 964cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton @SuppressWarnings("unchecked") // unsafe, which is one advantage of Cache over Map 965cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton @Override 966cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton public V get(Object key) { 967cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton V value; 968cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton try { 969cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton value = getOrCompute((K) key); 970cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton } catch (ExecutionException e) { 971cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton Throwable cause = e.getCause(); 972cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton Throwables.propagateIfInstanceOf(cause, ComputationException.class); 973cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton throw new ComputationException(cause); 974cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton } 975cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton 976cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton if (value == null) { 977cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton throw new NullPointerException(computingFunction + " returned null for key " + key + "."); 978cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton } 979cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton return value; 980cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton } 981cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton } 982cc4666fc64939f1a9a56a0cb5eb8a237942c5243Jeff Hamilton 9831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 984