aboutsummaryrefslogtreecommitdiffstats
path: root/guava/src/com/google/common/collect/Maps.java
diff options
context:
space:
mode:
Diffstat (limited to 'guava/src/com/google/common/collect/Maps.java')
-rw-r--r--guava/src/com/google/common/collect/Maps.java2126
1 files changed, 193 insertions, 1933 deletions
diff --git a/guava/src/com/google/common/collect/Maps.java b/guava/src/com/google/common/collect/Maps.java
index 9569a52..4215869 100644
--- a/guava/src/com/google/common/collect/Maps.java
+++ b/guava/src/com/google/common/collect/Maps.java
@@ -23,6 +23,7 @@ import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Equivalence;
+import com.google.common.base.Equivalences;
import com.google.common.base.Function;
import com.google.common.base.Joiner.MapJoiner;
import com.google.common.base.Objects;
@@ -35,6 +36,7 @@ import com.google.common.primitives.Ints;
import java.io.Serializable;
import java.util.AbstractCollection;
import java.util.AbstractMap;
+import java.util.AbstractSet;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
@@ -46,25 +48,17 @@ import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
-import java.util.NavigableMap;
-import java.util.NavigableSet;
import java.util.Properties;
import java.util.Set;
import java.util.SortedMap;
-import java.util.SortedSet;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentMap;
import javax.annotation.Nullable;
/**
- * Static utility methods pertaining to {@link Map} instances (including instances of
- * {@link SortedMap}, {@link BiMap}, etc.). Also see this class's counterparts
- * {@link Lists}, {@link Sets} and {@link Queues}.
- *
- * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained#Maps">
- * {@code Maps}</a>.
+ * Static utility methods pertaining to {@link Map} instances. Also see this
+ * class's counterparts {@link Lists} and {@link Sets}.
*
* @author Kevin Bourrillion
* @author Mike Bostock
@@ -76,60 +70,6 @@ import javax.annotation.Nullable;
public final class Maps {
private Maps() {}
- private enum EntryFunction implements Function<Entry, Object> {
- KEY {
- @Override
- @Nullable
- public Object apply(Entry entry) {
- return entry.getKey();
- }
- },
- VALUE {
- @Override
- @Nullable
- public Object apply(Entry entry) {
- return entry.getValue();
- }
- };
- }
-
- @SuppressWarnings("unchecked")
- static <K> Function<Entry<K, ?>, K> keyFunction() {
- return (Function) EntryFunction.KEY;
- }
-
- static <V> Function<Entry<?, V>, V> valueFunction() {
- return (Function) EntryFunction.VALUE;
- }
-
- /**
- * Returns an immutable map instance containing the given entries.
- * Internally, the returned set will be backed by an {@link EnumMap}.
- *
- * <p>The iteration order of the returned map follows the enum's iteration
- * order, not the order in which the elements appear in the given map.
- *
- * @param map the map to make an immutable copy of
- * @return an immutable map containing those entries
- * @since 14.0
- */
- @GwtCompatible(serializable = true)
- @Beta
- public static <K extends Enum<K>, V> ImmutableMap<K, V> immutableEnumMap(
- Map<K, V> map) {
- if (map instanceof ImmutableEnumMap) {
- return (ImmutableEnumMap<K, V>) map;
- } else if (map.isEmpty()) {
- return ImmutableMap.of();
- } else {
- for (Map.Entry<K, V> entry : map.entrySet()) {
- checkNotNull(entry.getKey());
- checkNotNull(entry.getValue());
- }
- return ImmutableEnumMap.asImmutable(new EnumMap<K, V>(map));
- }
- }
-
/**
* Creates a <i>mutable</i>, empty {@code HashMap} instance.
*
@@ -285,9 +225,9 @@ public final class Maps {
* @param comparator the comparator to sort the keys with
* @return a new, empty {@code TreeMap}
*/
- public static <C, K extends C, V> TreeMap<K, V> newTreeMap(
- @Nullable Comparator<C> comparator) {
- // Ideally, the extra type parameter "C" shouldn't be necessary. It is a
+ public static <K, V> TreeMap<K, V> newTreeMap(
+ @Nullable Comparator<? super K> comparator) {
+ // Ideally, the "? super" shouldn't be necessary. It is a
// work-around of a compiler type inference quirk that prevents the
// following code from being compiled:
// Comparator<Class<?>> comparator = null;
@@ -329,6 +269,38 @@ public final class Maps {
}
/**
+ * Returns a synchronized (thread-safe) bimap backed by the specified bimap.
+ * In order to guarantee serial access, it is critical that <b>all</b> access
+ * to the backing bimap is accomplished through the returned bimap.
+ *
+ * <p>It is imperative that the user manually synchronize on the returned map
+ * when accessing any of its collection views: <pre> {@code
+ *
+ * BiMap<Long, String> map = Maps.synchronizedBiMap(
+ * HashBiMap.<Long, String>create());
+ * ...
+ * Set<Long> set = map.keySet(); // Needn't be in synchronized block
+ * ...
+ * synchronized (map) { // Synchronizing on map, not set!
+ * Iterator<Long> it = set.iterator(); // Must be in synchronized block
+ * while (it.hasNext()) {
+ * foo(it.next());
+ * }
+ * }}</pre>
+ *
+ * Failure to follow this advice may result in non-deterministic behavior.
+ *
+ * <p>The returned bimap will be serializable if the specified bimap is
+ * serializable.
+ *
+ * @param bimap the bimap to be wrapped in a synchronized view
+ * @return a sychronized view of the specified bimap
+ */
+ public static <K, V> BiMap<K, V> synchronizedBiMap(BiMap<K, V> bimap) {
+ return Synchronized.biMap(bimap, null);
+ }
+
+ /**
* Computes the difference between two maps. This difference is an immutable
* snapshot of the state of the maps at the time this method is called. It
* will never change, even if the maps change at a later time.
@@ -352,7 +324,7 @@ public final class Maps {
SortedMapDifference<K, V> result = difference(sortedLeft, right);
return result;
}
- return difference(left, right, Equivalence.equals());
+ return difference(left, right, Equivalences.equals());
}
/**
@@ -524,7 +496,7 @@ public final class Maps {
}
@Override public boolean equals(@Nullable Object object) {
- if (object instanceof MapDifference.ValueDifference) {
+ if (object instanceof MapDifference.ValueDifference<?>) {
MapDifference.ValueDifference<?> that =
(MapDifference.ValueDifference<?>) object;
return Objects.equal(this.left, that.leftValue())
@@ -561,6 +533,7 @@ public final class Maps {
* @return the difference between the two maps
* @since 11.0
*/
+ @Beta
public static <K, V> SortedMapDifference<K, V> difference(
SortedMap<K, ? extends V> left, Map<? extends K, ? extends V> right) {
checkNotNull(left);
@@ -645,484 +618,6 @@ public final class Maps {
}
return (Comparator<E>) Ordering.natural();
}
-
- /**
- * Returns a view of the set as a map, mapping keys from the set according to
- * the specified function.
- *
- * <p>Specifically, for each {@code k} in the backing set, the returned map
- * has an entry mapping {@code k} to {@code function.apply(k)}. The {@code
- * keySet}, {@code values}, and {@code entrySet} views of the returned map
- * iterate in the same order as the backing set.
- *
- * <p>Modifications to the backing set are read through to the returned map.
- * The returned map supports removal operations if the backing set does.
- * Removal operations write through to the backing set. The returned map
- * does not support put operations.
- *
- * <p><b>Warning</b>: If the function rejects {@code null}, caution is
- * required to make sure the set does not contain {@code null}, because the
- * view cannot stop {@code null} from being added to the set.
- *
- * <p><b>Warning:</b> This method assumes that for any instance {@code k} of
- * key type {@code K}, {@code k.equals(k2)} implies that {@code k2} is also
- * of type {@code K}. Using a key type for which this may not hold, such as
- * {@code ArrayList}, may risk a {@code ClassCastException} when calling
- * methods on the resulting map view.
- *
- * @since 14.0
- */
- @Beta
- public static <K, V> Map<K, V> asMap(
- Set<K> set, Function<? super K, V> function) {
- if (set instanceof SortedSet) {
- return asMap((SortedSet<K>) set, function);
- } else {
- return new AsMapView<K, V>(set, function);
- }
- }
-
- /**
- * Returns a view of the sorted set as a map, mapping keys from the set
- * according to the specified function.
- *
- * <p>Specifically, for each {@code k} in the backing set, the returned map
- * has an entry mapping {@code k} to {@code function.apply(k)}. The {@code
- * keySet}, {@code values}, and {@code entrySet} views of the returned map
- * iterate in the same order as the backing set.
- *
- * <p>Modifications to the backing set are read through to the returned map.
- * The returned map supports removal operations if the backing set does.
- * Removal operations write through to the backing set. The returned map does
- * not support put operations.
- *
- * <p><b>Warning</b>: If the function rejects {@code null}, caution is
- * required to make sure the set does not contain {@code null}, because the
- * view cannot stop {@code null} from being added to the set.
- *
- * <p><b>Warning:</b> This method assumes that for any instance {@code k} of
- * key type {@code K}, {@code k.equals(k2)} implies that {@code k2} is also of
- * type {@code K}. Using a key type for which this may not hold, such as
- * {@code ArrayList}, may risk a {@code ClassCastException} when calling
- * methods on the resulting map view.
- *
- * @since 14.0
- */
- @Beta
- public static <K, V> SortedMap<K, V> asMap(
- SortedSet<K> set, Function<? super K, V> function) {
- return Platform.mapsAsMapSortedSet(set, function);
- }
-
- static <K, V> SortedMap<K, V> asMapSortedIgnoreNavigable(SortedSet<K> set,
- Function<? super K, V> function) {
- return new SortedAsMapView<K, V>(set, function);
- }
-
- /**
- * Returns a view of the navigable set as a map, mapping keys from the set
- * according to the specified function.
- *
- * <p>Specifically, for each {@code k} in the backing set, the returned map
- * has an entry mapping {@code k} to {@code function.apply(k)}. The {@code
- * keySet}, {@code values}, and {@code entrySet} views of the returned map
- * iterate in the same order as the backing set.
- *
- * <p>Modifications to the backing set are read through to the returned map.
- * The returned map supports removal operations if the backing set does.
- * Removal operations write through to the backing set. The returned map
- * does not support put operations.
- *
- * <p><b>Warning</b>: If the function rejects {@code null}, caution is
- * required to make sure the set does not contain {@code null}, because the
- * view cannot stop {@code null} from being added to the set.
- *
- * <p><b>Warning:</b> This method assumes that for any instance {@code k} of
- * key type {@code K}, {@code k.equals(k2)} implies that {@code k2} is also
- * of type {@code K}. Using a key type for which this may not hold, such as
- * {@code ArrayList}, may risk a {@code ClassCastException} when calling
- * methods on the resulting map view.
- *
- * @since 14.0
- */
- @Beta
- @GwtIncompatible("NavigableMap")
- public static <K, V> NavigableMap<K, V> asMap(
- NavigableSet<K> set, Function<? super K, V> function) {
- return new NavigableAsMapView<K, V>(set, function);
- }
-
- private static class AsMapView<K, V> extends ImprovedAbstractMap<K, V> {
-
- private final Set<K> set;
- final Function<? super K, V> function;
-
- Set<K> backingSet() {
- return set;
- }
-
- AsMapView(Set<K> set, Function<? super K, V> function) {
- this.set = checkNotNull(set);
- this.function = checkNotNull(function);
- }
-
- @Override
- public Set<K> keySet() {
- // probably not worth caching
- return removeOnlySet(backingSet());
- }
-
- @Override
- public Collection<V> values() {
- // probably not worth caching
- return Collections2.transform(set, function);
- }
-
- @Override
- public int size() {
- return backingSet().size();
- }
-
- @Override
- public boolean containsKey(@Nullable Object key) {
- return backingSet().contains(key);
- }
-
- @Override
- public V get(@Nullable Object key) {
- if (backingSet().contains(key)) {
- @SuppressWarnings("unchecked") // unsafe, but Javadoc warns about it
- K k = (K) key;
- return function.apply(k);
- } else {
- return null;
- }
- }
-
- @Override
- public V remove(@Nullable Object key) {
- if (backingSet().remove(key)) {
- @SuppressWarnings("unchecked") // unsafe, but Javadoc warns about it
- K k = (K) key;
- return function.apply(k);
- } else {
- return null;
- }
- }
-
- @Override
- public void clear() {
- backingSet().clear();
- }
-
- @Override
- protected Set<Entry<K, V>> createEntrySet() {
- return new EntrySet<K, V>() {
- @Override
- Map<K, V> map() {
- return AsMapView.this;
- }
-
- @Override
- public Iterator<Entry<K, V>> iterator() {
- return asSetEntryIterator(backingSet(), function);
- }
- };
- }
- }
-
- private static <K, V> Iterator<Entry<K, V>> asSetEntryIterator(
- Set<K> set, final Function<? super K, V> function) {
- return new TransformedIterator<K, Entry<K,V>>(set.iterator()) {
- @Override
- Entry<K, V> transform(K key) {
- return Maps.immutableEntry(key, function.apply(key));
- }
- };
- }
-
- private static class SortedAsMapView<K, V> extends AsMapView<K, V>
- implements SortedMap<K, V> {
-
- SortedAsMapView(SortedSet<K> set, Function<? super K, V> function) {
- super(set, function);
- }
-
- @Override
- SortedSet<K> backingSet() {
- return (SortedSet<K>) super.backingSet();
- }
-
- @Override
- public Comparator<? super K> comparator() {
- return backingSet().comparator();
- }
-
- @Override
- public Set<K> keySet() {
- return removeOnlySortedSet(backingSet());
- }
-
- @Override
- public SortedMap<K, V> subMap(K fromKey, K toKey) {
- return asMap(backingSet().subSet(fromKey, toKey), function);
- }
-
- @Override
- public SortedMap<K, V> headMap(K toKey) {
- return asMap(backingSet().headSet(toKey), function);
- }
-
- @Override
- public SortedMap<K, V> tailMap(K fromKey) {
- return asMap(backingSet().tailSet(fromKey), function);
- }
-
- @Override
- public K firstKey() {
- return backingSet().first();
- }
-
- @Override
- public K lastKey() {
- return backingSet().last();
- }
- }
-
- @GwtIncompatible("NavigableMap")
- private static final class NavigableAsMapView<K, V>
- extends AbstractNavigableMap<K, V> {
- /*
- * Using AbstractNavigableMap is simpler than extending SortedAsMapView and rewriting all the
- * NavigableMap methods.
- */
-
- private final NavigableSet<K> set;
- private final Function<? super K, V> function;
-
- NavigableAsMapView(NavigableSet<K> ks, Function<? super K, V> vFunction) {
- this.set = checkNotNull(ks);
- this.function = checkNotNull(vFunction);
- }
-
- @Override
- public NavigableMap<K, V> subMap(
- K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
- return asMap(set.subSet(fromKey, fromInclusive, toKey, toInclusive), function);
- }
-
- @Override
- public NavigableMap<K, V> headMap(K toKey, boolean inclusive) {
- return asMap(set.headSet(toKey, inclusive), function);
- }
-
- @Override
- public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive) {
- return asMap(set.tailSet(fromKey, inclusive), function);
- }
-
- @Override
- public Comparator<? super K> comparator() {
- return set.comparator();
- }
-
- @Override
- @Nullable
- public V get(@Nullable Object key) {
- if (set.contains(key)) {
- @SuppressWarnings("unchecked") // unsafe, but Javadoc warns about it
- K k = (K) key;
- return function.apply(k);
- } else {
- return null;
- }
- }
-
- @Override
- public void clear() {
- set.clear();
- }
-
- @Override
- Iterator<Entry<K, V>> entryIterator() {
- return asSetEntryIterator(set, function);
- }
-
- @Override
- Iterator<Entry<K, V>> descendingEntryIterator() {
- return descendingMap().entrySet().iterator();
- }
-
- @Override
- public NavigableSet<K> navigableKeySet() {
- return removeOnlyNavigableSet(set);
- }
-
- @Override
- public int size() {
- return set.size();
- }
-
- @Override
- public NavigableMap<K, V> descendingMap() {
- return asMap(set.descendingSet(), function);
- }
- }
-
- private static <E> Set<E> removeOnlySet(final Set<E> set) {
- return new ForwardingSet<E>() {
- @Override
- protected Set<E> delegate() {
- return set;
- }
-
- @Override
- public boolean add(E element) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean addAll(Collection<? extends E> es) {
- throw new UnsupportedOperationException();
- }
- };
- }
-
- private static <E> SortedSet<E> removeOnlySortedSet(final SortedSet<E> set) {
- return new ForwardingSortedSet<E>() {
- @Override
- protected SortedSet<E> delegate() {
- return set;
- }
-
- @Override
- public boolean add(E element) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean addAll(Collection<? extends E> es) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public SortedSet<E> headSet(E toElement) {
- return removeOnlySortedSet(super.headSet(toElement));
- }
-
- @Override
- public SortedSet<E> subSet(E fromElement, E toElement) {
- return removeOnlySortedSet(super.subSet(fromElement, toElement));
- }
-
- @Override
- public SortedSet<E> tailSet(E fromElement) {
- return removeOnlySortedSet(super.tailSet(fromElement));
- }
- };
- }
-
- @GwtIncompatible("NavigableSet")
- private static <E> NavigableSet<E> removeOnlyNavigableSet(final NavigableSet<E> set) {
- return new ForwardingNavigableSet<E>() {
- @Override
- protected NavigableSet<E> delegate() {
- return set;
- }
-
- @Override
- public boolean add(E element) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean addAll(Collection<? extends E> es) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public SortedSet<E> headSet(E toElement) {
- return removeOnlySortedSet(super.headSet(toElement));
- }
-
- @Override
- public SortedSet<E> subSet(E fromElement, E toElement) {
- return removeOnlySortedSet(
- super.subSet(fromElement, toElement));
- }
-
- @Override
- public SortedSet<E> tailSet(E fromElement) {
- return removeOnlySortedSet(super.tailSet(fromElement));
- }
-
- @Override
- public NavigableSet<E> headSet(E toElement, boolean inclusive) {
- return removeOnlyNavigableSet(super.headSet(toElement, inclusive));
- }
-
- @Override
- public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
- return removeOnlyNavigableSet(super.tailSet(fromElement, inclusive));
- }
-
- @Override
- public NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
- E toElement, boolean toInclusive) {
- return removeOnlyNavigableSet(super.subSet(
- fromElement, fromInclusive, toElement, toInclusive));
- }
-
- @Override
- public NavigableSet<E> descendingSet() {
- return removeOnlyNavigableSet(super.descendingSet());
- }
- };
- }
-
- /**
- * Returns an immutable map for which the given {@code keys} are mapped to
- * values by the given function in the order they appear in the original
- * iterable. If {@code keys} contains duplicate elements, the returned map
- * will contain each distinct key once in the order it first appears in
- * {@code keys}.
- *
- * @throws NullPointerException if any element of {@code keys} is
- * {@code null}, or if {@code valueFunction} produces {@code null}
- * for any key
- * @since 14.0
- */
- @Beta
- public static <K, V> ImmutableMap<K, V> toMap(Iterable<K> keys,
- Function<? super K, V> valueFunction) {
- return toMap(keys.iterator(), valueFunction);
- }
-
- /**
- * Returns an immutable map for which the given {@code keys} are mapped to
- * values by the given function in the order they appear in the original
- * iterator. If {@code keys} contains duplicate elements, the returned map
- * will contain each distinct key once in the order it first appears in
- * {@code keys}.
- *
- * @throws NullPointerException if any element of {@code keys} is
- * {@code null}, or if {@code valueFunction} produces {@code null}
- * for any key
- * @since 14.0
- */
- @Beta
- public static <K, V> ImmutableMap<K, V> toMap(Iterator<K> keys,
- Function<? super K, V> valueFunction) {
- checkNotNull(valueFunction);
- // Using LHM instead of a builder so as not to fail on duplicate keys
- Map<K, V> builder = newLinkedHashMap();
- while (keys.hasNext()) {
- K key = keys.next();
- builder.put(key, valueFunction.apply(key));
- }
- return ImmutableMap.copyOf(builder);
- }
-
/**
* Returns an immutable map for which the {@link Map#values} are the given
* elements in the given order, and each key is the product of invoking a
@@ -1143,6 +638,24 @@ public final class Maps {
}
/**
+ * <b>Deprecated.</b>
+ *
+ * @since 10.0
+ * @deprecated use {@link #uniqueIndex(Iterator, Function)} by casting {@code
+ * values} to {@code Iterator<V>}, or better yet, by implementing only
+ * {@code Iterator} and not {@code Iterable}. <b>This method is scheduled
+ * for deletion in March 2012.</b>
+ */
+ @Beta
+ @Deprecated
+ public static <K, V, I extends Object & Iterable<V> & Iterator<V>>
+ ImmutableMap<K, V> uniqueIndex(
+ I values, Function<? super V, K> keyFunction) {
+ Iterable<V> valuesIterable = checkNotNull(values);
+ return uniqueIndex(valuesIterable, keyFunction);
+ }
+
+ /**
* Returns an immutable map for which the {@link Map#values} are the given
* elements in the given order, and each key is the product of invoking a
* supplied function on its corresponding value.
@@ -1330,38 +843,6 @@ public final class Maps {
}
/**
- * Returns a synchronized (thread-safe) bimap backed by the specified bimap.
- * In order to guarantee serial access, it is critical that <b>all</b> access
- * to the backing bimap is accomplished through the returned bimap.
- *
- * <p>It is imperative that the user manually synchronize on the returned map
- * when accessing any of its collection views: <pre> {@code
- *
- * BiMap<Long, String> map = Maps.synchronizedBiMap(
- * HashBiMap.<Long, String>create());
- * ...
- * Set<Long> set = map.keySet(); // Needn't be in synchronized block
- * ...
- * synchronized (map) { // Synchronizing on map, not set!
- * Iterator<Long> it = set.iterator(); // Must be in synchronized block
- * while (it.hasNext()) {
- * foo(it.next());
- * }
- * }}</pre>
- *
- * Failure to follow this advice may result in non-deterministic behavior.
- *
- * <p>The returned bimap will be serializable if the specified bimap is
- * serializable.
- *
- * @param bimap the bimap to be wrapped in a synchronized view
- * @return a sychronized view of the specified bimap
- */
- public static <K, V> BiMap<K, V> synchronizedBiMap(BiMap<K, V> bimap) {
- return Synchronized.biMap(bimap, null);
- }
-
- /**
* Returns an unmodifiable view of the specified bimap. This method allows
* modules to provide users with "read-only" access to internal bimaps. Query
* operations on the returned bimap "read through" to the specified bimap, and
@@ -1384,7 +865,7 @@ public final class Maps {
extends ForwardingMap<K, V> implements BiMap<K, V>, Serializable {
final Map<K, V> unmodifiableMap;
final BiMap<? extends K, ? extends V> delegate;
- BiMap<V, K> inverse;
+ transient BiMap<V, K> inverse;
transient Set<V> values;
UnmodifiableBiMap(BiMap<? extends K, ? extends V> delegate,
@@ -1458,8 +939,16 @@ public final class Maps {
* a view, copy the returned map into a new map of your choosing.
*/
public static <K, V1, V2> Map<K, V2> transformValues(
- Map<K, V1> fromMap, Function<? super V1, V2> function) {
- return transformEntries(fromMap, asEntryTransformer(function));
+ Map<K, V1> fromMap, final Function<? super V1, V2> function) {
+ checkNotNull(function);
+ EntryTransformer<K, V1, V2> transformer =
+ new EntryTransformer<K, V1, V2>() {
+ @Override
+ public V2 transformEntry(K key, V1 value) {
+ return function.apply(value);
+ }
+ };
+ return transformEntries(fromMap, transformer);
}
/**
@@ -1501,67 +990,18 @@ public final class Maps {
*
* @since 11.0
*/
+ @Beta
public static <K, V1, V2> SortedMap<K, V2> transformValues(
- SortedMap<K, V1> fromMap, Function<? super V1, V2> function) {
- return transformEntries(fromMap, asEntryTransformer(function));
- }
-
- /**
- * Returns a view of a navigable map where each value is transformed by a
- * function. All other properties of the map, such as iteration order, are
- * left intact. For example, the code: <pre> {@code
- *
- * NavigableMap<String, Integer> map = Maps.newTreeMap();
- * map.put("a", 4);
- * map.put("b", 9);
- * Function<Integer, Double> sqrt =
- * new Function<Integer, Double>() {
- * public Double apply(Integer in) {
- * return Math.sqrt((int) in);
- * }
- * };
- * NavigableMap<String, Double> transformed =
- * Maps.transformNavigableValues(map, sqrt);
- * System.out.println(transformed);}</pre>
- *
- * ... prints {@code {a=2.0, b=3.0}}.
- *
- * Changes in the underlying map are reflected in this view.
- * Conversely, this view supports removal operations, and these are reflected
- * in the underlying map.
- *
- * <p>It's acceptable for the underlying map to contain null keys, and even
- * null values provided that the function is capable of accepting null input.
- * The transformed map might contain null values, if the function sometimes
- * gives a null result.
- *
- * <p>The returned map is not thread-safe or serializable, even if the
- * underlying map is.
- *
- * <p>The function is applied lazily, invoked when needed. This is necessary
- * for the returned map to be a view, but it means that the function will be
- * applied many times for bulk operations like {@link Map#containsValue} and
- * {@code Map.toString()}. For this to perform well, {@code function} should
- * be fast. To avoid lazy evaluation when the returned map doesn't need to be
- * a view, copy the returned map into a new map of your choosing.
- *
- * @since 13.0
- */
- @GwtIncompatible("NavigableMap")
- public static <K, V1, V2> NavigableMap<K, V2> transformValues(
- NavigableMap<K, V1> fromMap, Function<? super V1, V2> function) {
- return transformEntries(fromMap, asEntryTransformer(function));
- }
-
- private static <K, V1, V2> EntryTransformer<K, V1, V2>
- asEntryTransformer(final Function<? super V1, V2> function) {
+ SortedMap<K, V1> fromMap, final Function<? super V1, V2> function) {
checkNotNull(function);
- return new EntryTransformer<K, V1, V2>() {
- @Override
- public V2 transformEntry(K key, V1 value) {
- return function.apply(value);
- }
- };
+ EntryTransformer<K, V1, V2> transformer =
+ new EntryTransformer<K, V1, V2>() {
+ @Override
+ public V2 transformEntry(K key, V1 value) {
+ return function.apply(value);
+ }
+ };
+ return transformEntries(fromMap, transformer);
}
/**
@@ -1676,74 +1116,9 @@ public final class Maps {
*
* @since 11.0
*/
+ @Beta
public static <K, V1, V2> SortedMap<K, V2> transformEntries(
- SortedMap<K, V1> fromMap,
- EntryTransformer<? super K, ? super V1, V2> transformer) {
- return Platform.mapsTransformEntriesSortedMap(fromMap, transformer);
- }
-
- /**
- * Returns a view of a navigable map whose values are derived from the
- * original navigable map's entries. In contrast to {@link
- * #transformValues}, this method's entry-transformation logic may
- * depend on the key as well as the value.
- *
- * <p>All other properties of the transformed map, such as iteration order,
- * are left intact. For example, the code: <pre> {@code
- *
- * NavigableMap<String, Boolean> options = Maps.newTreeMap();
- * options.put("verbose", false);
- * options.put("sort", true);
- * EntryTransformer<String, Boolean, String> flagPrefixer =
- * new EntryTransformer<String, Boolean, String>() {
- * public String transformEntry(String key, Boolean value) {
- * return value ? key : ("yes" + key);
- * }
- * };
- * NavigableMap<String, String> transformed =
- * LabsMaps.transformNavigableEntries(options, flagPrefixer);
- * System.out.println(transformed);}</pre>
- *
- * ... prints {@code {sort=yessort, verbose=verbose}}.
- *
- * <p>Changes in the underlying map are reflected in this view.
- * Conversely, this view supports removal operations, and these are reflected
- * in the underlying map.
- *
- * <p>It's acceptable for the underlying map to contain null keys and null
- * values provided that the transformer is capable of accepting null inputs.
- * The transformed map might contain null values if the transformer sometimes
- * gives a null result.
- *
- * <p>The returned map is not thread-safe or serializable, even if the
- * underlying map is.
- *
- * <p>The transformer is applied lazily, invoked when needed. This is
- * necessary for the returned map to be a view, but it means that the
- * transformer will be applied many times for bulk operations like {@link
- * Map#containsValue} and {@link Object#toString}. For this to perform well,
- * {@code transformer} should be fast. To avoid lazy evaluation when the
- * returned map doesn't need to be a view, copy the returned map into a new
- * map of your choosing.
- *
- * <p><b>Warning:</b> This method assumes that for any instance {@code k} of
- * {@code EntryTransformer} key type {@code K}, {@code k.equals(k2)} implies
- * that {@code k2} is also of type {@code K}. Using an {@code
- * EntryTransformer} key type for which this may not hold, such as {@code
- * ArrayList}, may risk a {@code ClassCastException} when calling methods on
- * the transformed map.
- *
- * @since 13.0
- */
- @GwtIncompatible("NavigableMap")
- public static <K, V1, V2> NavigableMap<K, V2> transformEntries(
- final NavigableMap<K, V1> fromMap,
- EntryTransformer<? super K, ? super V1, V2> transformer) {
- return new TransformedEntriesNavigableMap<K, V1, V2>(fromMap, transformer);
- }
-
- static <K, V1, V2> SortedMap<K, V2> transformEntriesIgnoreNavigable(
- SortedMap<K, V1> fromMap,
+ final SortedMap<K, V1> fromMap,
EntryTransformer<? super K, ? super V1, V2> transformer) {
return new TransformedEntriesSortedMap<K, V1, V2>(fromMap, transformer);
}
@@ -1835,23 +1210,17 @@ public final class Maps {
}
@Override public Iterator<Entry<K, V2>> iterator() {
- return new TransformedIterator<Entry<K, V1>, Entry<K, V2>>(
- fromMap.entrySet().iterator()) {
- @Override
- Entry<K, V2> transform(final Entry<K, V1> entry) {
- return new AbstractMapEntry<K, V2>() {
- @Override
- public K getKey() {
- return entry.getKey();
+ final Iterator<Entry<K, V1>> backingIterator =
+ fromMap.entrySet().iterator();
+ return Iterators.transform(backingIterator,
+ new Function<Entry<K, V1>, Entry<K, V2>>() {
+ @Override public Entry<K, V2> apply(Entry<K, V1> entry) {
+ return immutableEntry(
+ entry.getKey(),
+ transformer.transformEntry(entry.getKey(),
+ entry.getValue()));
}
-
- @Override
- public V2 getValue() {
- return transformer.transformEntry(entry.getKey(), entry.getValue());
- }
- };
- }
- };
+ });
}
};
}
@@ -1909,144 +1278,7 @@ public final class Maps {
@Override public SortedMap<K, V2> tailMap(K fromKey) {
return transformEntries(fromMap().tailMap(fromKey), transformer);
}
- }
-
- @GwtIncompatible("NavigableMap")
- private static class TransformedEntriesNavigableMap<K, V1, V2>
- extends TransformedEntriesSortedMap<K, V1, V2>
- implements NavigableMap<K, V2> {
-
- TransformedEntriesNavigableMap(NavigableMap<K, V1> fromMap,
- EntryTransformer<? super K, ? super V1, V2> transformer) {
- super(fromMap, transformer);
- }
-
- @Override public Entry<K, V2> ceilingEntry(K key) {
- return transformEntry(fromMap().ceilingEntry(key));
- }
-
- @Override public K ceilingKey(K key) {
- return fromMap().ceilingKey(key);
- }
-
- @Override public NavigableSet<K> descendingKeySet() {
- return fromMap().descendingKeySet();
- }
-
- @Override public NavigableMap<K, V2> descendingMap() {
- return transformEntries(fromMap().descendingMap(), transformer);
- }
-
- @Override public Entry<K, V2> firstEntry() {
- return transformEntry(fromMap().firstEntry());
- }
- @Override public Entry<K, V2> floorEntry(K key) {
- return transformEntry(fromMap().floorEntry(key));
- }
-
- @Override public K floorKey(K key) {
- return fromMap().floorKey(key);
- }
-
- @Override public NavigableMap<K, V2> headMap(K toKey) {
- return headMap(toKey, false);
- }
-
- @Override public NavigableMap<K, V2> headMap(K toKey, boolean inclusive) {
- return transformEntries(
- fromMap().headMap(toKey, inclusive), transformer);
- }
-
- @Override public Entry<K, V2> higherEntry(K key) {
- return transformEntry(fromMap().higherEntry(key));
- }
-
- @Override public K higherKey(K key) {
- return fromMap().higherKey(key);
- }
-
- @Override public Entry<K, V2> lastEntry() {
- return transformEntry(fromMap().lastEntry());
- }
-
- @Override public Entry<K, V2> lowerEntry(K key) {
- return transformEntry(fromMap().lowerEntry(key));
- }
- @Override public K lowerKey(K key) {
- return fromMap().lowerKey(key);
- }
-
- @Override public NavigableSet<K> navigableKeySet() {
- return fromMap().navigableKeySet();
- }
-
- @Override public Entry<K, V2> pollFirstEntry() {
- return transformEntry(fromMap().pollFirstEntry());
- }
-
- @Override public Entry<K, V2> pollLastEntry() {
- return transformEntry(fromMap().pollLastEntry());
- }
-
- @Override public NavigableMap<K, V2> subMap(
- K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
- return transformEntries(
- fromMap().subMap(fromKey, fromInclusive, toKey, toInclusive),
- transformer);
- }
-
- @Override public NavigableMap<K, V2> subMap(K fromKey, K toKey) {
- return subMap(fromKey, true, toKey, false);
- }
-
- @Override public NavigableMap<K, V2> tailMap(K fromKey) {
- return tailMap(fromKey, true);
- }
-
- @Override public NavigableMap<K, V2> tailMap(K fromKey, boolean inclusive) {
- return transformEntries(
- fromMap().tailMap(fromKey, inclusive), transformer);
- }
-
- private Entry<K, V2> transformEntry(Entry<K, V1> entry) {
- if (entry == null) {
- return null;
- }
- K key = entry.getKey();
- V2 v2 = transformer.transformEntry(key, entry.getValue());
- return Maps.immutableEntry(key, v2);
- }
-
- @Override protected NavigableMap<K, V1> fromMap() {
- return (NavigableMap<K, V1>) super.fromMap();
- }
- }
-
- private static final class KeyPredicate<K, V> implements Predicate<Entry<K, V>> {
- private final Predicate<? super K> keyPredicate;
-
- KeyPredicate(Predicate<? super K> keyPredicate) {
- this.keyPredicate = checkNotNull(keyPredicate);
- }
-
- @Override
- public boolean apply(Entry<K, V> input) {
- return keyPredicate.apply(input.getKey());
- }
- }
-
- private static final class ValuePredicate<K, V> implements Predicate<Entry<K, V>> {
- private final Predicate<? super V> valuePredicate;
-
- ValuePredicate(Predicate<? super V> valuePredicate) {
- this.valuePredicate = checkNotNull(valuePredicate);
- }
-
- @Override
- public boolean apply(Entry<K, V> input) {
- return valuePredicate.apply(input.getValue());
- }
}
/**
@@ -2081,11 +1313,15 @@ public final class Maps {
Map<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
if (unfiltered instanceof SortedMap) {
return filterKeys((SortedMap<K, V>) unfiltered, keyPredicate);
- } else if (unfiltered instanceof BiMap) {
- return filterKeys((BiMap<K, V>) unfiltered, keyPredicate);
}
checkNotNull(keyPredicate);
- Predicate<Entry<K, V>> entryPredicate = new KeyPredicate<K, V>(keyPredicate);
+ Predicate<Entry<K, V>> entryPredicate =
+ new Predicate<Entry<K, V>>() {
+ @Override
+ public boolean apply(Entry<K, V> input) {
+ return keyPredicate.apply(input.getKey());
+ }
+ };
return (unfiltered instanceof AbstractFilteredMap)
? filterFiltered((AbstractFilteredMap<K, V>) unfiltered, entryPredicate)
: new FilteredKeyMap<K, V>(
@@ -2122,80 +1358,19 @@ public final class Maps {
*
* @since 11.0
*/
+ @Beta
public static <K, V> SortedMap<K, V> filterKeys(
SortedMap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
- // TODO(user): Return a subclass of Maps.FilteredKeyMap for slightly better
- // performance.
- return filterEntries(unfiltered, new KeyPredicate<K, V>(keyPredicate));
- }
-
- /**
- * Returns a navigable map containing the mappings in {@code unfiltered} whose
- * keys satisfy a predicate. The returned map is a live view of {@code
- * unfiltered}; changes to one affect the other.
- *
- * <p>The resulting map's {@code keySet()}, {@code entrySet()}, and {@code
- * values()} views have iterators that don't support {@code remove()}, but all
- * other methods are supported by the map and its views. When given a key that
- * doesn't satisfy the predicate, the map's {@code put()} and {@code putAll()}
- * methods throw an {@link IllegalArgumentException}.
- *
- * <p>When methods such as {@code removeAll()} and {@code clear()} are called
- * on the filtered map or its views, only mappings whose keys satisfy the
- * filter will be removed from the underlying map.
- *
- * <p>The returned map isn't threadsafe or serializable, even if {@code
- * unfiltered} is.
- *
- * <p>Many of the filtered map's methods, such as {@code size()},
- * iterate across every key/value mapping in the underlying map and determine
- * which satisfy the filter. When a live view is <i>not</i> needed, it may be
- * faster to copy the filtered map and use the copy.
- *
- * <p><b>Warning:</b> {@code keyPredicate} must be <i>consistent with
- * equals</i>, as documented at {@link Predicate#apply}. Do not provide a
- * predicate such as {@code Predicates.instanceOf(ArrayList.class)}, which is
- * inconsistent with equals.
- *
- * @since 14.0
- */
- @GwtIncompatible("NavigableMap")
- public static <K, V> NavigableMap<K, V> filterKeys(
- NavigableMap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
- // TODO(user): Return a subclass of Maps.FilteredKeyMap for slightly better
+ // TODO: Return a subclass of Maps.FilteredKeyMap for slightly better
// performance.
- return filterEntries(unfiltered, new KeyPredicate<K, V>(keyPredicate));
- }
-
- /**
- * Returns a bimap containing the mappings in {@code unfiltered} whose keys satisfy a predicate.
- * The returned bimap is a live view of {@code unfiltered}; changes to one affect the other.
- *
- * <p>The resulting bimap's {@code keySet()}, {@code entrySet()}, and {@code values()} views have
- * iterators that don't support {@code remove()}, but all other methods are supported by the
- * bimap and its views. When given a key that doesn't satisfy the predicate, the bimap's {@code
- * put()}, {@code forcePut()} and {@code putAll()} methods throw an {@link
- * IllegalArgumentException}.
- *
- * <p>When methods such as {@code removeAll()} and {@code clear()} are called on the filtered
- * bimap or its views, only mappings that satisfy the filter will be removed from the underlying
- * bimap.
- *
- * <p>The returned bimap isn't threadsafe or serializable, even if {@code unfiltered} is.
- *
- * <p>Many of the filtered bimap's methods, such as {@code size()}, iterate across every key in
- * the underlying bimap and determine which satisfy the filter. When a live view is <i>not</i>
- * needed, it may be faster to copy the filtered bimap and use the copy.
- *
- * <p><b>Warning:</b> {@code entryPredicate} must be <i>consistent with equals </i>, as
- * documented at {@link Predicate#apply}.
- *
- * @since 14.0
- */
- public static <K, V> BiMap<K, V> filterKeys(
- BiMap<K, V> unfiltered, final Predicate<? super K> keyPredicate) {
checkNotNull(keyPredicate);
- return filterEntries(unfiltered, new KeyPredicate<K, V>(keyPredicate));
+ Predicate<Entry<K, V>> entryPredicate = new Predicate<Entry<K, V>>() {
+ @Override
+ public boolean apply(Entry<K, V> input) {
+ return keyPredicate.apply(input.getKey());
+ }
+ };
+ return filterEntries(unfiltered, entryPredicate);
}
/**
@@ -2231,10 +1406,16 @@ public final class Maps {
Map<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
if (unfiltered instanceof SortedMap) {
return filterValues((SortedMap<K, V>) unfiltered, valuePredicate);
- } else if (unfiltered instanceof BiMap) {
- return filterValues((BiMap<K, V>) unfiltered, valuePredicate);
}
- return filterEntries(unfiltered, new ValuePredicate<K, V>(valuePredicate));
+ checkNotNull(valuePredicate);
+ Predicate<Entry<K, V>> entryPredicate =
+ new Predicate<Entry<K, V>>() {
+ @Override
+ public boolean apply(Entry<K, V> input) {
+ return valuePredicate.apply(input.getValue());
+ }
+ };
+ return filterEntries(unfiltered, entryPredicate);
}
/**
@@ -2268,79 +1449,18 @@ public final class Maps {
*
* @since 11.0
*/
+ @Beta
public static <K, V> SortedMap<K, V> filterValues(
SortedMap<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
- return filterEntries(unfiltered, new ValuePredicate<K, V>(valuePredicate));
- }
-
- /**
- * Returns a navigable map containing the mappings in {@code unfiltered} whose
- * values satisfy a predicate. The returned map is a live view of {@code
- * unfiltered}; changes to one affect the other.
- *
- * <p>The resulting map's {@code keySet()}, {@code entrySet()}, and {@code
- * values()} views have iterators that don't support {@code remove()}, but all
- * other methods are supported by the map and its views. When given a value
- * that doesn't satisfy the predicate, the map's {@code put()}, {@code
- * putAll()}, and {@link Entry#setValue} methods throw an {@link
- * IllegalArgumentException}.
- *
- * <p>When methods such as {@code removeAll()} and {@code clear()} are called
- * on the filtered map or its views, only mappings whose values satisfy the
- * filter will be removed from the underlying map.
- *
- * <p>The returned map isn't threadsafe or serializable, even if {@code
- * unfiltered} is.
- *
- * <p>Many of the filtered map's methods, such as {@code size()},
- * iterate across every key/value mapping in the underlying map and determine
- * which satisfy the filter. When a live view is <i>not</i> needed, it may be
- * faster to copy the filtered map and use the copy.
- *
- * <p><b>Warning:</b> {@code valuePredicate} must be <i>consistent with
- * equals</i>, as documented at {@link Predicate#apply}. Do not provide a
- * predicate such as {@code Predicates.instanceOf(ArrayList.class)}, which is
- * inconsistent with equals.
- *
- * @since 14.0
- */
- @GwtIncompatible("NavigableMap")
- public static <K, V> NavigableMap<K, V> filterValues(
- NavigableMap<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
- return filterEntries(unfiltered, new ValuePredicate<K, V>(valuePredicate));
- }
-
- /**
- * Returns a bimap containing the mappings in {@code unfiltered} whose values satisfy a
- * predicate. The returned bimap is a live view of {@code unfiltered}; changes to one affect the
- * other.
- *
- * <p>The resulting bimap's {@code keySet()}, {@code entrySet()}, and {@code values()} views have
- * iterators that don't support {@code remove()}, but all other methods are supported by the
- * bimap and its views. When given a value that doesn't satisfy the predicate, the bimap's
- * {@code put()}, {@code forcePut()} and {@code putAll()} methods throw an {@link
- * IllegalArgumentException}. Similarly, the map's entries have a {@link Entry#setValue} method
- * that throws an {@link IllegalArgumentException} when the provided value doesn't satisfy the
- * predicate.
- *
- * <p>When methods such as {@code removeAll()} and {@code clear()} are called on the filtered
- * bimap or its views, only mappings that satisfy the filter will be removed from the underlying
- * bimap.
- *
- * <p>The returned bimap isn't threadsafe or serializable, even if {@code unfiltered} is.
- *
- * <p>Many of the filtered bimap's methods, such as {@code size()}, iterate across every value in
- * the underlying bimap and determine which satisfy the filter. When a live view is <i>not</i>
- * needed, it may be faster to copy the filtered bimap and use the copy.
- *
- * <p><b>Warning:</b> {@code entryPredicate} must be <i>consistent with equals </i>, as
- * documented at {@link Predicate#apply}.
- *
- * @since 14.0
- */
- public static <K, V> BiMap<K, V> filterValues(
- BiMap<K, V> unfiltered, final Predicate<? super V> valuePredicate) {
- return filterEntries(unfiltered, new ValuePredicate<K, V>(valuePredicate));
+ checkNotNull(valuePredicate);
+ Predicate<Entry<K, V>> entryPredicate =
+ new Predicate<Entry<K, V>>() {
+ @Override
+ public boolean apply(Entry<K, V> input) {
+ return valuePredicate.apply(input.getValue());
+ }
+ };
+ return filterEntries(unfiltered, entryPredicate);
}
/**
@@ -2376,8 +1496,6 @@ public final class Maps {
Map<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
if (unfiltered instanceof SortedMap) {
return filterEntries((SortedMap<K, V>) unfiltered, entryPredicate);
- } else if (unfiltered instanceof BiMap) {
- return filterEntries((BiMap<K, V>) unfiltered, entryPredicate);
}
checkNotNull(entryPredicate);
return (unfiltered instanceof AbstractFilteredMap)
@@ -2416,15 +1534,10 @@ public final class Maps {
*
* @since 11.0
*/
+ @Beta
public static <K, V> SortedMap<K, V> filterEntries(
SortedMap<K, V> unfiltered,
Predicate<? super Entry<K, V>> entryPredicate) {
- return Platform.mapsFilterSortedMap(unfiltered, entryPredicate);
- }
-
- static <K, V> SortedMap<K, V> filterSortedIgnoreNavigable(
- SortedMap<K, V> unfiltered,
- Predicate<? super Entry<K, V>> entryPredicate) {
checkNotNull(entryPredicate);
return (unfiltered instanceof FilteredEntrySortedMap)
? filterFiltered((FilteredEntrySortedMap<K, V>) unfiltered, entryPredicate)
@@ -2432,83 +1545,6 @@ public final class Maps {
}
/**
- * Returns a sorted map containing the mappings in {@code unfiltered} that
- * satisfy a predicate. The returned map is a live view of {@code unfiltered};
- * changes to one affect the other.
- *
- * <p>The resulting map's {@code keySet()}, {@code entrySet()}, and {@code
- * values()} views have iterators that don't support {@code remove()}, but all
- * other methods are supported by the map and its views. When given a
- * key/value pair that doesn't satisfy the predicate, the map's {@code put()}
- * and {@code putAll()} methods throw an {@link IllegalArgumentException}.
- * Similarly, the map's entries have a {@link Entry#setValue} method that
- * throws an {@link IllegalArgumentException} when the existing key and the
- * provided value don't satisfy the predicate.
- *
- * <p>When methods such as {@code removeAll()} and {@code clear()} are called
- * on the filtered map or its views, only mappings that satisfy the filter
- * will be removed from the underlying map.
- *
- * <p>The returned map isn't threadsafe or serializable, even if {@code
- * unfiltered} is.
- *
- * <p>Many of the filtered map's methods, such as {@code size()},
- * iterate across every key/value mapping in the underlying map and determine
- * which satisfy the filter. When a live view is <i>not</i> needed, it may be
- * faster to copy the filtered map and use the copy.
- *
- * <p><b>Warning:</b> {@code entryPredicate} must be <i>consistent with
- * equals</i>, as documented at {@link Predicate#apply}.
- *
- * @since 14.0
- */
- @GwtIncompatible("NavigableMap")
- public static <K, V> NavigableMap<K, V> filterEntries(
- NavigableMap<K, V> unfiltered,
- Predicate<? super Entry<K, V>> entryPredicate) {
- checkNotNull(entryPredicate);
- return (unfiltered instanceof FilteredEntryNavigableMap)
- ? filterFiltered((FilteredEntryNavigableMap<K, V>) unfiltered, entryPredicate)
- : new FilteredEntryNavigableMap<K, V>(checkNotNull(unfiltered), entryPredicate);
- }
-
- /**
- * Returns a bimap containing the mappings in {@code unfiltered} that satisfy a predicate. The
- * returned bimap is a live view of {@code unfiltered}; changes to one affect the other.
- *
- * <p>The resulting bimap's {@code keySet()}, {@code entrySet()}, and {@code values()} views have
- * iterators that don't support {@code remove()}, but all other methods are supported by the bimap
- * and its views. When given a key/value pair that doesn't satisfy the predicate, the bimap's
- * {@code put()}, {@code forcePut()} and {@code putAll()} methods throw an
- * {@link IllegalArgumentException}. Similarly, the map's entries have an {@link Entry#setValue}
- * method that throws an {@link IllegalArgumentException} when the existing key and the provided
- * value don't satisfy the predicate.
- *
- * <p>When methods such as {@code removeAll()} and {@code clear()} are called on the filtered
- * bimap or its views, only mappings that satisfy the filter will be removed from the underlying
- * bimap.
- *
- * <p>The returned bimap isn't threadsafe or serializable, even if {@code unfiltered} is.
- *
- * <p>Many of the filtered bimap's methods, such as {@code size()}, iterate across every
- * key/value mapping in the underlying bimap and determine which satisfy the filter. When a live
- * view is <i>not</i> needed, it may be faster to copy the filtered bimap and use the copy.
- *
- * <p><b>Warning:</b> {@code entryPredicate} must be <i>consistent with equals </i>, as
- * documented at {@link Predicate#apply}.
- *
- * @since 14.0
- */
- public static <K, V> BiMap<K, V> filterEntries(
- BiMap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
- checkNotNull(unfiltered);
- checkNotNull(entryPredicate);
- return (unfiltered instanceof FilteredEntryBiMap)
- ? filterFiltered((FilteredEntryBiMap<K, V>) unfiltered, entryPredicate)
- : new FilteredEntryBiMap<K, V>(unfiltered, entryPredicate);
- }
-
- /**
* Support {@code clear()}, {@code removeAll()}, and {@code retainAll()} when
* filtering a filtered map.
*/
@@ -2653,7 +1689,6 @@ public final class Maps {
}
}
}
-
/**
* Support {@code clear()}, {@code removeAll()}, and {@code retainAll()} when
* filtering a filtered sorted map.
@@ -2714,251 +1749,6 @@ public final class Maps {
}
}
- /**
- * Support {@code clear()}, {@code removeAll()}, and {@code retainAll()} when
- * filtering a filtered navigable map.
- */
- @GwtIncompatible("NavigableMap")
- private static <K, V> NavigableMap<K, V> filterFiltered(
- FilteredEntryNavigableMap<K, V> map,
- Predicate<? super Entry<K, V>> entryPredicate) {
- Predicate<Entry<K, V>> predicate
- = Predicates.and(map.predicate, entryPredicate);
- return new FilteredEntryNavigableMap<K, V>(map.sortedMap(), predicate);
- }
-
- @GwtIncompatible("NavigableMap")
- private static class FilteredEntryNavigableMap<K, V> extends FilteredEntrySortedMap<K, V>
- implements NavigableMap<K, V> {
-
- FilteredEntryNavigableMap(
- NavigableMap<K, V> unfiltered, Predicate<? super Entry<K, V>> entryPredicate) {
- super(unfiltered, entryPredicate);
- }
-
- @Override
- NavigableMap<K, V> sortedMap() {
- return (NavigableMap<K, V>) super.sortedMap();
- }
-
- @Override
- public Entry<K, V> lowerEntry(K key) {
- return headMap(key, false).lastEntry();
- }
-
- @Override
- public K lowerKey(K key) {
- return keyOrNull(lowerEntry(key));
- }
-
- @Override
- public Entry<K, V> floorEntry(K key) {
- return headMap(key, true).lastEntry();
- }
-
- @Override
- public K floorKey(K key) {
- return keyOrNull(floorEntry(key));
- }
-
- @Override
- public Entry<K, V> ceilingEntry(K key) {
- return tailMap(key, true).firstEntry();
- }
-
- @Override
- public K ceilingKey(K key) {
- return keyOrNull(ceilingEntry(key));
- }
-
- @Override
- public Entry<K, V> higherEntry(K key) {
- return tailMap(key, false).firstEntry();
- }
-
- @Override
- public K higherKey(K key) {
- return keyOrNull(higherEntry(key));
- }
-
- @Override
- public Entry<K, V> firstEntry() {
- return Iterables.getFirst(entrySet(), null);
- }
-
- @Override
- public Entry<K, V> lastEntry() {
- return Iterables.getFirst(descendingMap().entrySet(), null);
- }
-
- @Override
- public Entry<K, V> pollFirstEntry() {
- return pollFirstSatisfyingEntry(sortedMap().entrySet().iterator());
- }
-
- @Override
- public Entry<K, V> pollLastEntry() {
- return pollFirstSatisfyingEntry(sortedMap().descendingMap().entrySet().iterator());
- }
-
- @Nullable
- Entry<K, V> pollFirstSatisfyingEntry(Iterator<Entry<K, V>> entryIterator) {
- while (entryIterator.hasNext()) {
- Entry<K, V> entry = entryIterator.next();
- if (predicate.apply(entry)) {
- entryIterator.remove();
- return entry;
- }
- }
- return null;
- }
-
- @Override
- public NavigableMap<K, V> descendingMap() {
- return filterEntries(sortedMap().descendingMap(), predicate);
- }
-
- @Override
- public NavigableSet<K> keySet() {
- return (NavigableSet<K>) super.keySet();
- }
-
- @Override
- NavigableSet<K> createKeySet() {
- return new NavigableKeySet<K, V>(this) {
- @Override
- public boolean removeAll(Collection<?> c) {
- boolean changed = false;
- Iterator<Entry<K, V>> entryIterator = sortedMap().entrySet().iterator();
- while (entryIterator.hasNext()) {
- Entry<K, V> entry = entryIterator.next();
- if (c.contains(entry.getKey()) && predicate.apply(entry)) {
- entryIterator.remove();
- changed = true;
- }
- }
- return changed;
- }
-
- @Override
- public boolean retainAll(Collection<?> c) {
- boolean changed = false;
- Iterator<Entry<K, V>> entryIterator = sortedMap().entrySet().iterator();
- while (entryIterator.hasNext()) {
- Entry<K, V> entry = entryIterator.next();
- if (!c.contains(entry.getKey()) && predicate.apply(entry)) {
- entryIterator.remove();
- changed = true;
- }
- }
- return changed;
- }
- };
- }
-
- @Override
- public NavigableSet<K> navigableKeySet() {
- return keySet();
- }
-
- @Override
- public NavigableSet<K> descendingKeySet() {
- return descendingMap().navigableKeySet();
- }
-
- @Override
- public NavigableMap<K, V> subMap(K fromKey, K toKey) {
- return subMap(fromKey, true, toKey, false);
- }
-
- @Override
- public NavigableMap<K, V> subMap(
- K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
- return filterEntries(
- sortedMap().subMap(fromKey, fromInclusive, toKey, toInclusive), predicate);
- }
-
- @Override
- public NavigableMap<K, V> headMap(K toKey) {
- return headMap(toKey, false);
- }
-
- @Override
- public NavigableMap<K, V> headMap(K toKey, boolean inclusive) {
- return filterEntries(sortedMap().headMap(toKey, inclusive), predicate);
- }
-
- @Override
- public NavigableMap<K, V> tailMap(K fromKey) {
- return tailMap(fromKey, true);
- }
-
- @Override
- public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive) {
- return filterEntries(sortedMap().tailMap(fromKey, inclusive), predicate);
- }
- }
-
- /**
- * Support {@code clear()}, {@code removeAll()}, and {@code retainAll()} when
- * filtering a filtered map.
- */
- private static <K, V> BiMap<K, V> filterFiltered(
- FilteredEntryBiMap<K, V> map, Predicate<? super Entry<K, V>> entryPredicate) {
- Predicate<Entry<K, V>> predicate = Predicates.and(map.predicate, entryPredicate);
- return new FilteredEntryBiMap<K, V>(map.unfiltered(), predicate);
- }
-
- static final class FilteredEntryBiMap<K, V> extends FilteredEntryMap<K, V>
- implements BiMap<K, V> {
- private final BiMap<V, K> inverse;
-
- private static <K, V> Predicate<Entry<V, K>> inversePredicate(
- final Predicate<? super Entry<K, V>> forwardPredicate) {
- return new Predicate<Entry<V, K>>() {
- @Override
- public boolean apply(Entry<V, K> input) {
- return forwardPredicate.apply(
- Maps.immutableEntry(input.getValue(), input.getKey()));
- }
- };
- }
-
- FilteredEntryBiMap(BiMap<K, V> delegate,
- Predicate<? super Entry<K, V>> predicate) {
- super(delegate, predicate);
- this.inverse = new FilteredEntryBiMap<V, K>(
- delegate.inverse(), inversePredicate(predicate), this);
- }
-
- private FilteredEntryBiMap(
- BiMap<K, V> delegate, Predicate<? super Entry<K, V>> predicate,
- BiMap<V, K> inverse) {
- super(delegate, predicate);
- this.inverse = inverse;
- }
-
- BiMap<K, V> unfiltered() {
- return (BiMap<K, V>) unfiltered;
- }
-
- @Override
- public V forcePut(@Nullable K key, @Nullable V value) {
- checkArgument(predicate.apply(Maps.immutableEntry(key, value)));
- return unfiltered().forcePut(key, value);
- }
-
- @Override
- public BiMap<V, K> inverse() {
- return inverse;
- }
-
- @Override
- public Set<V> values() {
- return inverse.keySet();
- }
- }
-
private static class FilteredKeyMap<K, V> extends AbstractFilteredMap<K, V> {
Predicate<? super K> keyPredicate;
@@ -3050,14 +1840,10 @@ public final class Maps {
@Override public Set<K> keySet() {
Set<K> result = keySet;
- return (result == null) ? keySet = createKeySet() : result;
+ return (result == null) ? keySet = new KeySet() : result;
}
- Set<K> createKeySet() {
- return new KeySet();
- }
-
- private class KeySet extends Sets.ImprovedAbstractSet<K> {
+ private class KeySet extends AbstractSet<K> {
@Override public Iterator<K> iterator() {
final Iterator<Entry<K, V>> iterator = filteredEntrySet.iterator();
return new UnmodifiableIterator<K>() {
@@ -3093,13 +1879,22 @@ public final class Maps {
return false;
}
+ @Override public boolean removeAll(Collection<?> collection) {
+ checkNotNull(collection); // for GWT
+ boolean changed = false;
+ for (Object obj : collection) {
+ changed |= remove(obj);
+ }
+ return changed;
+ }
+
@Override public boolean retainAll(Collection<?> collection) {
checkNotNull(collection); // for GWT
boolean changed = false;
Iterator<Entry<K, V>> iterator = unfiltered.entrySet().iterator();
while (iterator.hasNext()) {
Entry<K, V> entry = iterator.next();
- if (predicate.apply(entry) && !collection.contains(entry.getKey())) {
+ if (!collection.contains(entry.getKey()) && predicate.apply(entry)) {
iterator.remove();
changed = true;
}
@@ -3119,224 +1914,6 @@ public final class Maps {
}
/**
- * Returns an unmodifiable view of the specified navigable map. Query operations on the returned
- * map read through to the specified map, and attempts to modify the returned map, whether direct
- * or via its views, result in an {@code UnsupportedOperationException}.
- *
- * <p>The returned navigable map will be serializable if the specified navigable map is
- * serializable.
- *
- * @param map the navigable map for which an unmodifiable view is to be returned
- * @return an unmodifiable view of the specified navigable map
- * @since 12.0
- */
- @GwtIncompatible("NavigableMap")
- public static <K, V> NavigableMap<K, V> unmodifiableNavigableMap(NavigableMap<K, V> map) {
- checkNotNull(map);
- if (map instanceof UnmodifiableNavigableMap) {
- return map;
- } else {
- return new UnmodifiableNavigableMap<K, V>(map);
- }
- }
-
- @Nullable private static <K, V> Entry<K, V> unmodifiableOrNull(@Nullable Entry<K, V> entry) {
- return (entry == null) ? null : Maps.unmodifiableEntry(entry);
- }
-
- @GwtIncompatible("NavigableMap")
- static class UnmodifiableNavigableMap<K, V>
- extends ForwardingSortedMap<K, V> implements NavigableMap<K, V>, Serializable {
- private final NavigableMap<K, V> delegate;
-
- UnmodifiableNavigableMap(NavigableMap<K, V> delegate) {
- this.delegate = delegate;
- }
-
- @Override
- protected SortedMap<K, V> delegate() {
- return Collections.unmodifiableSortedMap(delegate);
- }
-
- @Override
- public Entry<K, V> lowerEntry(K key) {
- return unmodifiableOrNull(delegate.lowerEntry(key));
- }
-
- @Override
- public K lowerKey(K key) {
- return delegate.lowerKey(key);
- }
-
- @Override
- public Entry<K, V> floorEntry(K key) {
- return unmodifiableOrNull(delegate.floorEntry(key));
- }
-
- @Override
- public K floorKey(K key) {
- return delegate.floorKey(key);
- }
-
- @Override
- public Entry<K, V> ceilingEntry(K key) {
- return unmodifiableOrNull(delegate.ceilingEntry(key));
- }
-
- @Override
- public K ceilingKey(K key) {
- return delegate.ceilingKey(key);
- }
-
- @Override
- public Entry<K, V> higherEntry(K key) {
- return unmodifiableOrNull(delegate.higherEntry(key));
- }
-
- @Override
- public K higherKey(K key) {
- return delegate.higherKey(key);
- }
-
- @Override
- public Entry<K, V> firstEntry() {
- return unmodifiableOrNull(delegate.firstEntry());
- }
-
- @Override
- public Entry<K, V> lastEntry() {
- return unmodifiableOrNull(delegate.lastEntry());
- }
-
- @Override
- public final Entry<K, V> pollFirstEntry() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public final Entry<K, V> pollLastEntry() {
- throw new UnsupportedOperationException();
- }
-
- private transient UnmodifiableNavigableMap<K, V> descendingMap;
-
- @Override
- public NavigableMap<K, V> descendingMap() {
- UnmodifiableNavigableMap<K, V> result = descendingMap;
- if (result == null) {
- descendingMap = result = new UnmodifiableNavigableMap<K, V>(delegate.descendingMap());
- result.descendingMap = this;
- }
- return result;
- }
-
- @Override
- public Set<K> keySet() {
- return navigableKeySet();
- }
-
- @Override
- public NavigableSet<K> navigableKeySet() {
- return Sets.unmodifiableNavigableSet(delegate.navigableKeySet());
- }
-
- @Override
- public NavigableSet<K> descendingKeySet() {
- return Sets.unmodifiableNavigableSet(delegate.descendingKeySet());
- }
-
- @Override
- public SortedMap<K, V> subMap(K fromKey, K toKey) {
- return subMap(fromKey, true, toKey, false);
- }
-
- @Override
- public SortedMap<K, V> headMap(K toKey) {
- return headMap(toKey, false);
- }
-
- @Override
- public SortedMap<K, V> tailMap(K fromKey) {
- return tailMap(fromKey, true);
- }
-
- @Override
- public
- NavigableMap<K, V>
- subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
- return Maps.unmodifiableNavigableMap(delegate.subMap(
- fromKey,
- fromInclusive,
- toKey,
- toInclusive));
- }
-
- @Override
- public NavigableMap<K, V> headMap(K toKey, boolean inclusive) {
- return Maps.unmodifiableNavigableMap(delegate.headMap(toKey, inclusive));
- }
-
- @Override
- public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive) {
- return Maps.unmodifiableNavigableMap(delegate.tailMap(fromKey, inclusive));
- }
- }
-
- /**
- * Returns a synchronized (thread-safe) navigable map backed by the specified
- * navigable map. In order to guarantee serial access, it is critical that
- * <b>all</b> access to the backing navigable map is accomplished
- * through the returned navigable map (or its views).
- *
- * <p>It is imperative that the user manually synchronize on the returned
- * navigable map when iterating over any of its collection views, or the
- * collections views of any of its {@code descendingMap}, {@code subMap},
- * {@code headMap} or {@code tailMap} views. <pre> {@code
- *
- * NavigableMap<K, V> map = synchronizedNavigableMap(new TreeMap<K, V>());
- *
- * // Needn't be in synchronized block
- * NavigableSet<K> set = map.navigableKeySet();
- *
- * synchronized (map) { // Synchronizing on map, not set!
- * Iterator<K> it = set.iterator(); // Must be in synchronized block
- * while (it.hasNext()){
- * foo(it.next());
- * }
- * }}</pre>
- *
- * or: <pre> {@code
- *
- * NavigableMap<K, V> map = synchronizedNavigableMap(new TreeMap<K, V>());
- * NavigableMap<K, V> map2 = map.subMap(foo, false, bar, true);
- *
- * // Needn't be in synchronized block
- * NavigableSet<K> set2 = map2.descendingKeySet();
- *
- * synchronized (map) { // Synchronizing on map, not map2 or set2!
- * Iterator<K> it = set2.iterator(); // Must be in synchronized block
- * while (it.hasNext()){
- * foo(it.next());
- * }
- * }}</pre>
- *
- * Failure to follow this advice may result in non-deterministic behavior.
- *
- * <p>The returned navigable map will be serializable if the specified
- * navigable map is serializable.
- *
- * @param navigableMap the navigable map to be "wrapped" in a synchronized
- * navigable map.
- * @return a synchronized view of the specified navigable map.
- * @since 13.0
- */
- @GwtIncompatible("NavigableMap")
- public static <K, V> NavigableMap<K, V> synchronizedNavigableMap(
- NavigableMap<K, V> navigableMap) {
- return Synchronized.navigableMap(navigableMap);
- }
-
- /**
* {@code AbstractMap} extension that implements {@link #isEmpty()} as {@code
* entrySet().isEmpty()} instead of {@code size() == 0} to speed up
* implementations where {@code size()} is O(n), and it delegates the {@code
@@ -3344,7 +1921,7 @@ public final class Maps {
* implementation.
*/
@GwtCompatible
- abstract static class ImprovedAbstractMap<K, V> extends AbstractMap<K, V> {
+ static abstract class ImprovedAbstractMap<K, V> extends AbstractMap<K, V> {
/**
* Creates the entry set to be returned by {@link #entrySet()}. This method
* is invoked at most once on a given map, at the time when {@code entrySet}
@@ -3381,7 +1958,7 @@ public final class Maps {
@Override public Collection<V> values() {
Collection<V> result = values;
if (result == null) {
- return values = new Values<K, V>() {
+ return values = new Values<K, V>(){
@Override Map<K, V> map() {
return ImprovedAbstractMap.this;
}
@@ -3389,6 +1966,17 @@ public final class Maps {
}
return result;
}
+
+ /**
+ * Returns {@code true} if this map contains no key-value mappings.
+ *
+ * <p>The implementation returns {@code entrySet().isEmpty()}.
+ *
+ * @return {@code true} if this map contains no key-value mappings
+ */
+ @Override public boolean isEmpty() {
+ return entrySet().isEmpty();
+ }
}
static final MapJoiner STANDARD_JOINER =
@@ -3396,46 +1984,25 @@ public final class Maps {
/**
* Delegates to {@link Map#get}. Returns {@code null} on {@code
- * ClassCastException} and {@code NullPointerException}.
+ * ClassCastException}.
*/
static <V> V safeGet(Map<?, V> map, Object key) {
- checkNotNull(map);
try {
return map.get(key);
} catch (ClassCastException e) {
return null;
- } catch (NullPointerException e) {
- return null;
}
}
/**
* Delegates to {@link Map#containsKey}. Returns {@code false} on {@code
- * ClassCastException} and {@code NullPointerException}.
+ * ClassCastException}
*/
static boolean safeContainsKey(Map<?, ?> map, Object key) {
- checkNotNull(map);
try {
return map.containsKey(key);
} catch (ClassCastException e) {
return false;
- } catch (NullPointerException e) {
- return false;
- }
- }
-
- /**
- * Delegates to {@link Map#remove}. Returns {@code null} on {@code
- * ClassCastException} and {@code NullPointerException}.
- */
- static <V> V safeRemove(Map<?, V> map, Object key) {
- checkNotNull(map);
- try {
- return map.remove(key);
- } catch (ClassCastException e) {
- return null;
- } catch (NullPointerException e) {
- return null;
}
}
@@ -3494,6 +2061,13 @@ public final class Maps {
}
/**
+ * An implementation of {@link Map#hashCode}.
+ */
+ static int hashCodeImpl(Map<?, ?> map) {
+ return Sets.hashCodeImpl(map.entrySet());
+ }
+
+ /**
* An implementation of {@link Map#toString}.
*/
static String toStringImpl(Map<?, ?> map) {
@@ -3517,30 +2091,36 @@ public final class Maps {
* An admittedly inefficient implementation of {@link Map#containsKey}.
*/
static boolean containsKeyImpl(Map<?, ?> map, @Nullable Object key) {
- return Iterators.contains(keyIterator(map.entrySet().iterator()), key);
+ for (Entry<?, ?> entry : map.entrySet()) {
+ if (Objects.equal(entry.getKey(), key)) {
+ return true;
+ }
+ }
+ return false;
}
/**
* An implementation of {@link Map#containsValue}.
*/
static boolean containsValueImpl(Map<?, ?> map, @Nullable Object value) {
- return Iterators.contains(valueIterator(map.entrySet().iterator()), value);
- }
-
- static <K, V> Iterator<K> keyIterator(Iterator<Entry<K, V>> entryIterator) {
- return new TransformedIterator<Entry<K, V>, K>(entryIterator) {
- @Override
- K transform(Entry<K, V> entry) {
- return entry.getKey();
+ for (Entry<?, ?> entry : map.entrySet()) {
+ if (Objects.equal(entry.getValue(), value)) {
+ return true;
}
- };
+ }
+ return false;
}
- abstract static class KeySet<K, V> extends Sets.ImprovedAbstractSet<K> {
+ abstract static class KeySet<K, V> extends AbstractSet<K> {
abstract Map<K, V> map();
@Override public Iterator<K> iterator() {
- return keyIterator(map().entrySet().iterator());
+ return Iterators.transform(map().entrySet().iterator(),
+ new Function<Map.Entry<K, V>, K>() {
+ @Override public K apply(Entry<K, V> entry) {
+ return entry.getKey();
+ }
+ });
}
@Override public int size() {
@@ -3563,153 +2143,27 @@ public final class Maps {
return false;
}
- @Override public void clear() {
- map().clear();
- }
- }
-
- @Nullable
- static <K> K keyOrNull(@Nullable Entry<K, ?> entry) {
- return (entry == null) ? null : entry.getKey();
- }
-
- @Nullable
- static <V> V valueOrNull(@Nullable Entry<?, V> entry) {
- return (entry == null) ? null : entry.getValue();
- }
-
- @GwtIncompatible("NavigableMap")
- static class NavigableKeySet<K, V> extends KeySet<K, V> implements NavigableSet<K> {
- private final NavigableMap<K, V> map;
-
- NavigableKeySet(NavigableMap<K, V> map) {
- this.map = checkNotNull(map);
- }
-
- @Override
- NavigableMap<K, V> map() {
- return map;
- }
-
- @Override
- public Comparator<? super K> comparator() {
- return map().comparator();
- }
-
- @Override
- public K first() {
- return map().firstKey();
- }
-
- @Override
- public K last() {
- return map().lastKey();
- }
-
- @Override
- public K lower(K e) {
- return map().lowerKey(e);
- }
-
- @Override
- public K floor(K e) {
- return map().floorKey(e);
- }
-
- @Override
- public K ceiling(K e) {
- return map().ceilingKey(e);
- }
-
- @Override
- public K higher(K e) {
- return map().higherKey(e);
- }
-
- @Override
- public K pollFirst() {
- return keyOrNull(map().pollFirstEntry());
- }
-
- @Override
- public K pollLast() {
- return keyOrNull(map().pollLastEntry());
- }
-
- @Override
- public NavigableSet<K> descendingSet() {
- return map().descendingKeySet();
- }
-
- @Override
- public Iterator<K> descendingIterator() {
- return descendingSet().iterator();
- }
-
- @Override
- public NavigableSet<K> subSet(
- K fromElement,
- boolean fromInclusive,
- K toElement,
- boolean toInclusive) {
- return map().subMap(fromElement, fromInclusive, toElement, toInclusive).navigableKeySet();
- }
-
- @Override
- public NavigableSet<K> headSet(K toElement, boolean inclusive) {
- return map().headMap(toElement, inclusive).navigableKeySet();
- }
-
- @Override
- public NavigableSet<K> tailSet(K fromElement, boolean inclusive) {
- return map().tailMap(fromElement, inclusive).navigableKeySet();
- }
-
- @Override
- public SortedSet<K> subSet(K fromElement, K toElement) {
- return subSet(fromElement, true, toElement, false);
- }
-
@Override
- public SortedSet<K> headSet(K toElement) {
- return headSet(toElement, false);
+ public boolean removeAll(Collection<?> c) {
+ // TODO(user): find out why this is necessary to make GWT tests pass.
+ return super.removeAll(checkNotNull(c));
}
- @Override
- public SortedSet<K> tailSet(K fromElement) {
- return tailSet(fromElement, true);
+ @Override public void clear() {
+ map().clear();
}
}
- static <K, V> Iterator<V> valueIterator(Iterator<Entry<K, V>> entryIterator) {
- return new TransformedIterator<Entry<K, V>, V>(entryIterator) {
- @Override
- V transform(Entry<K, V> entry) {
- return entry.getValue();
- }
- };
- }
-
- static <K, V> UnmodifiableIterator<V> valueIterator(
- final UnmodifiableIterator<Entry<K, V>> entryIterator) {
- return new UnmodifiableIterator<V>() {
- @Override
- public boolean hasNext() {
- return entryIterator.hasNext();
- }
-
- @Override
- public V next() {
- return entryIterator.next().getValue();
- }
- };
- }
-
abstract static class Values<K, V> extends AbstractCollection<V> {
abstract Map<K, V> map();
@Override public Iterator<V> iterator() {
- return valueIterator(map().entrySet().iterator());
+ return Iterators.transform(map().entrySet().iterator(),
+ new Function<Entry<K, V>, V>() {
+ @Override public V apply(Entry<K, V> entry) {
+ return entry.getValue();
+ }
+ });
}
@Override public boolean remove(Object o) {
@@ -3771,8 +2225,7 @@ public final class Maps {
}
}
- abstract static class EntrySet<K, V>
- extends Sets.ImprovedAbstractSet<Entry<K, V>> {
+ abstract static class EntrySet<K, V> extends AbstractSet<Entry<K, V>> {
abstract Map<K, V> map();
@Override public int size() {
@@ -3835,197 +2288,4 @@ public final class Maps {
}
}
}
-
- @GwtIncompatible("NavigableMap")
- abstract static class DescendingMap<K, V> extends ForwardingMap<K, V>
- implements NavigableMap<K, V> {
-
- abstract NavigableMap<K, V> forward();
-
- @Override
- protected final Map<K, V> delegate() {
- return forward();
- }
-
- private transient Comparator<? super K> comparator;
-
- @SuppressWarnings("unchecked")
- @Override
- public Comparator<? super K> comparator() {
- Comparator<? super K> result = comparator;
- if (result == null) {
- Comparator<? super K> forwardCmp = forward().comparator();
- if (forwardCmp == null) {
- forwardCmp = (Comparator) Ordering.natural();
- }
- result = comparator = reverse(forwardCmp);
- }
- return result;
- }
-
- // If we inline this, we get a javac error.
- private static <T> Ordering<T> reverse(Comparator<T> forward) {
- return Ordering.from(forward).reverse();
- }
-
- @Override
- public K firstKey() {
- return forward().lastKey();
- }
-
- @Override
- public K lastKey() {
- return forward().firstKey();
- }
-
- @Override
- public Entry<K, V> lowerEntry(K key) {
- return forward().higherEntry(key);
- }
-
- @Override
- public K lowerKey(K key) {
- return forward().higherKey(key);
- }
-
- @Override
- public Entry<K, V> floorEntry(K key) {
- return forward().ceilingEntry(key);
- }
-
- @Override
- public K floorKey(K key) {
- return forward().ceilingKey(key);
- }
-
- @Override
- public Entry<K, V> ceilingEntry(K key) {
- return forward().floorEntry(key);
- }
-
- @Override
- public K ceilingKey(K key) {
- return forward().floorKey(key);
- }
-
- @Override
- public Entry<K, V> higherEntry(K key) {
- return forward().lowerEntry(key);
- }
-
- @Override
- public K higherKey(K key) {
- return forward().lowerKey(key);
- }
-
- @Override
- public Entry<K, V> firstEntry() {
- return forward().lastEntry();
- }
-
- @Override
- public Entry<K, V> lastEntry() {
- return forward().firstEntry();
- }
-
- @Override
- public Entry<K, V> pollFirstEntry() {
- return forward().pollLastEntry();
- }
-
- @Override
- public Entry<K, V> pollLastEntry() {
- return forward().pollFirstEntry();
- }
-
- @Override
- public NavigableMap<K, V> descendingMap() {
- return forward();
- }
-
- private transient Set<Entry<K, V>> entrySet;
-
- @Override
- public Set<Entry<K, V>> entrySet() {
- Set<Entry<K, V>> result = entrySet;
- return (result == null) ? entrySet = createEntrySet() : result;
- }
-
- abstract Iterator<Entry<K, V>> entryIterator();
-
- Set<Entry<K, V>> createEntrySet() {
- return new EntrySet<K, V>() {
-
- @Override
- Map<K, V> map() {
- return DescendingMap.this;
- }
-
- @Override
- public Iterator<Entry<K, V>> iterator() {
- return entryIterator();
- }
- };
- }
-
- @Override
- public Set<K> keySet() {
- return navigableKeySet();
- }
-
- private transient NavigableSet<K> navigableKeySet;
-
- @Override
- public NavigableSet<K> navigableKeySet() {
- NavigableSet<K> result = navigableKeySet;
- return (result == null) ? navigableKeySet = new NavigableKeySet<K, V>(this) : result;
- }
-
- @Override
- public NavigableSet<K> descendingKeySet() {
- return forward().navigableKeySet();
- }
-
- @Override
- public
- NavigableMap<K, V>
- subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
- return forward().subMap(toKey, toInclusive, fromKey, fromInclusive).descendingMap();
- }
-
- @Override
- public NavigableMap<K, V> headMap(K toKey, boolean inclusive) {
- return forward().tailMap(toKey, inclusive).descendingMap();
- }
-
- @Override
- public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive) {
- return forward().headMap(fromKey, inclusive).descendingMap();
- }
-
- @Override
- public SortedMap<K, V> subMap(K fromKey, K toKey) {
- return subMap(fromKey, true, toKey, false);
- }
-
- @Override
- public SortedMap<K, V> headMap(K toKey) {
- return headMap(toKey, false);
- }
-
- @Override
- public SortedMap<K, V> tailMap(K fromKey) {
- return tailMap(fromKey, true);
- }
-
- @Override
- public Collection<V> values() {
- return new Values<K, V>() {
- @Override
- Map<K, V> map() {
- return DescendingMap.this;
- }
- };
- }
- }
}