aboutsummaryrefslogtreecommitdiffstats
path: root/guava/src/com/google/common/collect/MapMaker.java
diff options
context:
space:
mode:
Diffstat (limited to 'guava/src/com/google/common/collect/MapMaker.java')
-rw-r--r--guava/src/com/google/common/collect/MapMaker.java147
1 files changed, 117 insertions, 30 deletions
diff --git a/guava/src/com/google/common/collect/MapMaker.java b/guava/src/com/google/common/collect/MapMaker.java
index a5a035e..330018e 100644
--- a/guava/src/com/google/common/collect/MapMaker.java
+++ b/guava/src/com/google/common/collect/MapMaker.java
@@ -18,12 +18,12 @@ import static com.google.common.base.Objects.firstNonNull;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.MapMakerInternalMap.Strength.SOFT;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Ascii;
import com.google.common.base.Equivalence;
+import com.google.common.base.Equivalences;
import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.base.Throwables;
@@ -51,6 +51,8 @@ import javax.annotation.Nullable;
* <ul>
* <li>keys or values automatically wrapped in {@linkplain WeakReference weak} or {@linkplain
* SoftReference soft} references
+ * <li>least-recently-used eviction when a maximum size is exceeded
+ * <li>time-based expiration of entries, measured since last access or last write
* <li>notification of evicted (or otherwise removed) entries
* <li>on-demand computation of values for keys not already present
* </ul>
@@ -60,6 +62,8 @@ import javax.annotation.Nullable;
* ConcurrentMap<Key, Graph> graphs = new MapMaker()
* .concurrencyLevel(4)
* .weakKeys()
+ * .maximumSize(10000)
+ * .expireAfterWrite(10, TimeUnit.MINUTES)
* .makeComputingMap(
* new Function<Key, Graph>() {
* public Graph apply(Key key) {
@@ -75,9 +79,10 @@ import javax.annotation.Nullable;
* interface. It does not permit null keys or values.
*
* <p><b>Note:</b> by default, the returned map uses equality comparisons (the {@link Object#equals
- * equals} method) to determine equality for keys or values. However, if {@link #weakKeys} was
- * specified, the map uses identity ({@code ==}) comparisons instead for keys. Likewise, if {@link
- * #weakValues} or {@link #softValues} was specified, the map uses identity comparisons for values.
+ * equals} method) to determine equality for keys or values. However, if {@link #weakKeys} or {@link
+ * #softKeys} was specified, the map uses identity ({@code ==}) comparisons instead for keys.
+ * Likewise, if {@link #weakValues} or {@link #softValues} was specified, the map uses identity
+ * comparisons for values.
*
* <p>The view collections of the returned map have <i>weakly consistent iterators</i>. This means
* that they are safe for concurrent use, but if other threads modify the map after the iterator is
@@ -129,6 +134,7 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
RemovalCause nullRemovalCause;
Equivalence<Object> keyEquivalence;
+ Equivalence<Object> valueEquivalence;
Ticker ticker;
@@ -138,12 +144,16 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
*/
public MapMaker() {}
+ private boolean useNullMap() {
+ return (nullRemovalCause == null);
+ }
+
/**
* Sets a custom {@code Equivalence} strategy for comparing keys.
*
- * <p>By default, the map uses {@link Equivalence#identity} to determine key equality when {@link
- * #weakKeys} is specified, and {@link Equivalence#equals()} otherwise. The only place this is
- * used is in {@link Interners.WeakInterner}.
+ * <p>By default, the map uses {@link Equivalences#identity} to determine key equality when
+ * {@link #weakKeys} or {@link #softKeys} is specified, and {@link Equivalences#equals()}
+ * otherwise.
*/
@GwtIncompatible("To be supported")
@Override
@@ -159,6 +169,27 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
}
/**
+ * Sets a custom {@code Equivalence} strategy for comparing values.
+ *
+ * <p>By default, the map uses {@link Equivalences#identity} to determine value equality when
+ * {@link #weakValues} or {@link #softValues} is specified, and {@link Equivalences#equals()}
+ * otherwise.
+ */
+ @GwtIncompatible("To be supported")
+ @Override
+ MapMaker valueEquivalence(Equivalence<Object> equivalence) {
+ checkState(valueEquivalence == null,
+ "value equivalence was already set to %s", valueEquivalence);
+ this.valueEquivalence = checkNotNull(equivalence);
+ this.useCustomMap = true;
+ return this;
+ }
+
+ Equivalence<Object> getValueEquivalence() {
+ return firstNonNull(valueEquivalence, getValueStrength().defaultEquivalence());
+ }
+
+ /**
* Sets the minimum total size for the internal hash tables. For example, if the initial capacity
* is {@code 60}, and the concurrency level is {@code 8}, then eight segments are created, each
* having a hash table of size eight. Providing a large enough estimate at construction time
@@ -200,9 +231,7 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
* @throws IllegalStateException if a maximum size was already set
* @deprecated Caching functionality in {@code MapMaker} is being moved to
* {@link com.google.common.cache.CacheBuilder}, with {@link #maximumSize} being
- * replaced by {@link com.google.common.cache.CacheBuilder#maximumSize}. Note that {@code
- * CacheBuilder} is simply an enhanced API for an implementation which was branched from
- * {@code MapMaker}.
+ * replaced by {@link com.google.common.cache.CacheBuilder#maximumSize}.
*/
@Deprecated
@Override
@@ -252,6 +281,16 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
}
/**
+ * Specifies that each key (not value) stored in the map should be strongly referenced.
+ *
+ * @throws IllegalStateException if the key strength was already set
+ */
+ @Override
+ MapMaker strongKeys() {
+ return setKeyStrength(Strength.STRONG);
+ }
+
+ /**
* Specifies that each key (not value) stored in the map should be wrapped in a {@link
* WeakReference} (by default, strong references are used).
*
@@ -268,10 +307,36 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
return setKeyStrength(Strength.WEAK);
}
+ /**
+ * <b>This method is broken.</b> Maps with soft keys offer no functional advantage over maps with
+ * weak keys, and they waste memory by keeping unreachable elements in the map. If your goal is to
+ * create a memory-sensitive map, then consider using soft values instead.
+ *
+ * <p>Specifies that each key (not value) stored in the map should be wrapped in a
+ * {@link SoftReference} (by default, strong references are used). Softly-referenced objects will
+ * be garbage-collected in a <i>globally</i> least-recently-used manner, in response to memory
+ * demand.
+ *
+ * <p><b>Warning:</b> when this method is used, the resulting map will use identity ({@code ==})
+ * comparison to determine equality of keys, which is a technical violation of the {@link Map}
+ * specification, and may not be what you expect.
+ *
+ * @throws IllegalStateException if the key strength was already set
+ * @see SoftReference
+ * @deprecated use {@link #softValues} to create a memory-sensitive map, or {@link #weakKeys} to
+ * create a map that doesn't hold strong references to the keys.
+ * <b>This method is scheduled for deletion in January 2013.</b>
+ */
+ @Deprecated
+ @GwtIncompatible("java.lang.ref.SoftReference")
+ @Override
+ public MapMaker softKeys() {
+ return setKeyStrength(Strength.SOFT);
+ }
+
MapMaker setKeyStrength(Strength strength) {
checkState(keyStrength == null, "Key strength was already set to %s", keyStrength);
keyStrength = checkNotNull(strength);
- checkArgument(keyStrength != SOFT, "Soft keys are not supported");
if (strength != Strength.STRONG) {
// STRONG could be used during deserialization.
useCustomMap = true;
@@ -284,6 +349,16 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
}
/**
+ * Specifies that each value (not key) stored in the map should be strongly referenced.
+ *
+ * @throws IllegalStateException if the value strength was already set
+ */
+ @Override
+ MapMaker strongValues() {
+ return setValueStrength(Strength.STRONG);
+ }
+
+ /**
* Specifies that each value (not key) stored in the map should be wrapped in a
* {@link WeakReference} (by default, strong references are used).
*
@@ -347,6 +422,22 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
}
/**
+ * Old name of {@link #expireAfterWrite}.
+ *
+ * @deprecated Caching functionality in {@code MapMaker} is being moved to
+ * {@link com.google.common.cache.CacheBuilder}. Functionality equivalent to
+ * {@link MapMaker#expiration} is provided by
+ * {@link com.google.common.cache.CacheBuilder#expireAfterWrite}.
+ * <b>This method is scheduled for deletion in July 2012.</b>
+ */
+ @Deprecated
+ @Override
+ public
+ MapMaker expiration(long duration, TimeUnit unit) {
+ return expireAfterWrite(duration, unit);
+ }
+
+ /**
* Specifies that each entry should be automatically removed from the map once a fixed duration
* has elapsed after the entry's creation, or the most recent replacement of its value.
*
@@ -367,9 +458,7 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
* @throws IllegalStateException if the time to live or time to idle was already set
* @deprecated Caching functionality in {@code MapMaker} is being moved to
* {@link com.google.common.cache.CacheBuilder}, with {@link #expireAfterWrite} being
- * replaced by {@link com.google.common.cache.CacheBuilder#expireAfterWrite}. Note that {@code
- * CacheBuilder} is simply an enhanced API for an implementation which was branched from
- * {@code MapMaker}.
+ * replaced by {@link com.google.common.cache.CacheBuilder#expireAfterWrite}.
*/
@Deprecated
@Override
@@ -417,9 +506,7 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
* @throws IllegalStateException if the time to idle or time to live was already set
* @deprecated Caching functionality in {@code MapMaker} is being moved to
* {@link com.google.common.cache.CacheBuilder}, with {@link #expireAfterAccess} being
- * replaced by {@link com.google.common.cache.CacheBuilder#expireAfterAccess}. Note that
- * {@code CacheBuilder} is simply an enhanced API for an implementation which was branched
- * from {@code MapMaker}.
+ * replaced by {@link com.google.common.cache.CacheBuilder#expireAfterAccess}.
*/
@Deprecated
@GwtIncompatible("To be supported")
@@ -469,9 +556,7 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
* @throws IllegalStateException if a removal listener was already set
* @deprecated Caching functionality in {@code MapMaker} is being moved to
* {@link com.google.common.cache.CacheBuilder}, with {@link #removalListener} being
- * replaced by {@link com.google.common.cache.CacheBuilder#removalListener}. Note that {@code
- * CacheBuilder} is simply an enhanced API for an implementation which was branched from
- * {@code MapMaker}.
+ * replaced by {@link com.google.common.cache.CacheBuilder#removalListener}.
*/
@Deprecated
@GwtIncompatible("To be supported")
@@ -571,16 +656,17 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
* @return a serializable concurrent map having the requested features
* @deprecated Caching functionality in {@code MapMaker} is being moved to
* {@link com.google.common.cache.CacheBuilder}, with {@link #makeComputingMap} being replaced
- * by {@link com.google.common.cache.CacheBuilder#build}. See the
- * <a href="http://code.google.com/p/guava-libraries/wiki/MapMakerMigration">MapMaker
- * Migration Guide</a> for more details.
+ * by {@link com.google.common.cache.CacheBuilder#build}. Note that uses of
+ * {@link #makeComputingMap} with {@code AtomicLong} values can often be migrated to
+ * {@link AtomicLongMap}.
* <b>This method is scheduled for deletion in February 2013.</b>
+ *
*/
@Deprecated
@Override
public <K, V> ConcurrentMap<K, V> makeComputingMap(
Function<? super K, ? extends V> computingFunction) {
- return (nullRemovalCause == null)
+ return useNullMap()
? new MapMaker.ComputingMapAdapter<K, V>(this, computingFunction)
: new NullComputingConcurrentMap<K, V>(this, computingFunction);
}
@@ -616,6 +702,9 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
if (keyEquivalence != null) {
s.addValue("keyEquivalence");
}
+ if (valueEquivalence != null) {
+ s.addValue("valueEquivalence");
+ }
if (removalListener != null) {
s.addValue("removalListener");
}
@@ -706,8 +795,9 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
},
/**
- * The entry was removed automatically because its key or value was garbage-collected. This can
- * occur when using {@link #softValues}, {@link #weakKeys}, or {@link #weakValues}.
+ * The entry was removed automatically because its key or value was garbage-collected. This
+ * can occur when using {@link #softKeys}, {@link #softValues}, {@link #weakKeys}, or {@link
+ * #weakValues}.
*/
COLLECTED {
@Override
@@ -862,10 +952,6 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
* Overrides get() to compute on demand. Also throws an exception when {@code null} is returned
* from a computation.
*/
- /*
- * This might make more sense in ComputingConcurrentHashMap, but it causes a javac crash in some
- * cases there: http://code.google.com/p/guava-libraries/issues/detail?id=950
- */
static final class ComputingMapAdapter<K, V>
extends ComputingConcurrentHashMap<K, V> implements Serializable {
private static final long serialVersionUID = 0;
@@ -893,4 +979,5 @@ public final class MapMaker extends GenericMapMaker<Object, Object> {
return value;
}
}
+
}