All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.docx4j.com.google.common.collect.Maps Maven / Gradle / Ivy

Go to download

docx4j is a library which helps you to work with the Office Open XML file format as used in docx documents, pptx presentations, and xlsx spreadsheets.

There is a newer version: 11.4.11
Show newest version
/*
 * Copyright (C) 2007 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.docx4j.com.google.common.collect;

import static org.docx4j.com.google.common.base.Preconditions.checkNotNull;

import java.util.AbstractMap;
import java.util.Collection;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedMap;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Consumer;

import org.apache.commons.compress.utils.Lists;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.docx4j.com.google.common.annotations.GwtCompatible;
import org.docx4j.com.google.common.base.Function;
import org.docx4j.com.google.common.base.Objects;
import org.docx4j.com.google.common.collect.Maps.EntryTransformer;
import org.docx4j.com.google.common.primitives.Ints;

/**
 * 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}.
 *
 * 

See the Guava User Guide article on {@code Maps}. * * @author Kevin Bourrillion * @author Mike Bostock * @author Isaac Shum * @author Louis Wasserman * @since 2.0 */ @GwtCompatible(emulated = true) public final class Maps { private Maps() {} private enum EntryFunction implements Function, Object> { KEY { @Override public @Nullable Object apply(Entry entry) { return entry.getKey(); } }, VALUE { @Override public @Nullable Object apply(Entry entry) { return entry.getValue(); } }; } @SuppressWarnings("unchecked") static Function, K> keyFunction() { return (Function) EntryFunction.KEY; } @SuppressWarnings("unchecked") static Function, V> valueFunction() { return (Function) EntryFunction.VALUE; } static Iterator keyIterator(Iterator> entryIterator) { return new TransformedIterator, K>(entryIterator) { @Override K transform(Entry entry) { return entry.getKey(); } }; } // // static Iterator valueIterator(Iterator> entryIterator) { // return new TransformedIterator, V>(entryIterator) { // @Override // V transform(Entry entry) { // return entry.getValue(); // } // }; // } // /** // * Returns an immutable map instance containing the given entries. Internally, the returned map // * will be backed by an {@link EnumMap}. // * // *

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) // public static , V> ImmutableMap immutableEnumMap( // Map map) { // if (map instanceof ImmutableEnumMap) { // @SuppressWarnings("unchecked") // safe covariant cast // ImmutableEnumMap result = (ImmutableEnumMap) map; // return result; // } // Iterator> entryItr = map.entrySet().iterator(); // if (!entryItr.hasNext()) { // return ImmutableMap.of(); // } // Entry entry1 = entryItr.next(); // K key1 = entry1.getKey(); // V value1 = entry1.getValue(); // checkEntryNotNull(key1, value1); // Class clazz = key1.getDeclaringClass(); // EnumMap enumMap = new EnumMap<>(clazz); // enumMap.put(key1, value1); // while (entryItr.hasNext()) { // Entry entry = entryItr.next(); // K key = entry.getKey(); // V value = entry.getValue(); // checkEntryNotNull(key, value); // enumMap.put(key, value); // } // return ImmutableEnumMap.asImmutable(enumMap); // } // // private static class Accumulator, V> { // private final BinaryOperator mergeFunction; // private EnumMap map = null; // // Accumulator(BinaryOperator mergeFunction) { // this.mergeFunction = mergeFunction; // } // // void put(K key, V value) { // if (map == null) { // map = new EnumMap<>(key.getDeclaringClass()); // } // map.merge(key, value, mergeFunction); // } // // Accumulator combine(Accumulator other) { // if (this.map == null) { // return other; // } else if (other.map == null) { // return this; // } else { // other.map.forEach(this::put); // return this; // } // } // // ImmutableMap toImmutableMap() { // return (map == null) ? ImmutableMap.of() : ImmutableEnumMap.asImmutable(map); // } // } // // /** // * Returns a {@link Collector} that accumulates elements into an {@code ImmutableMap} whose keys // * and values are the result of applying the provided mapping functions to the input elements. The // * resulting implementation is specialized for enum key types. The returned map and its views will // * iterate over keys in their enum definition order, not encounter order. // * // *

If the mapped keys contain duplicates, an {@code IllegalArgumentException} is thrown when // * the collection operation is performed. (This differs from the {@code Collector} returned by // * {@link java.util.stream.Collectors#toMap(java.util.function.Function, // * java.util.function.Function) Collectors.toMap(Function, Function)}, which throws an {@code // * IllegalStateException}.) // * // * @since 21.0 // */ // public static , V> Collector> toImmutableEnumMap( // java.util.function.Function keyFunction, // java.util.function.Function valueFunction) { // checkNotNull(keyFunction); // checkNotNull(valueFunction); // return Collector.of( // () -> // new Accumulator( // (v1, v2) -> { // throw new IllegalArgumentException("Multiple values for key: " + v1 + ", " + v2); // }), // (accum, t) -> { // K key = checkNotNull(keyFunction.apply(t), "Null key for input %s", t); // V newValue = checkNotNull(valueFunction.apply(t), "Null value for input %s", t); // accum.put(key, newValue); // }, // Accumulator::combine, // Accumulator::toImmutableMap, // Collector.Characteristics.UNORDERED); // } // // /** // * Returns a {@link Collector} that accumulates elements into an {@code ImmutableMap} whose keys // * and values are the result of applying the provided mapping functions to the input elements. The // * resulting implementation is specialized for enum key types. The returned map and its views will // * iterate over keys in their enum definition order, not encounter order. // * // *

If the mapped keys contain duplicates, the values are merged using the specified merging // * function. // * // * @since 21.0 // */ // public static , V> Collector> toImmutableEnumMap( // java.util.function.Function keyFunction, // java.util.function.Function valueFunction, // BinaryOperator mergeFunction) { // checkNotNull(keyFunction); // checkNotNull(valueFunction); // checkNotNull(mergeFunction); // // not UNORDERED because we don't know if mergeFunction is commutative // return Collector.of( // () -> new Accumulator(mergeFunction), // (accum, t) -> { // K key = checkNotNull(keyFunction.apply(t), "Null key for input %s", t); // V newValue = checkNotNull(valueFunction.apply(t), "Null value for input %s", t); // accum.put(key, newValue); // }, // Accumulator::combine, // Accumulator::toImmutableMap); // } /** * Creates a mutable, empty {@code HashMap} instance. * *

Note: if mutability is not required, use {@link ImmutableMap#of()} instead. * *

Note: if {@code K} is an {@code enum} type, use {@link #newEnumMap} instead. * *

Note for Java 7 and later: this method is now unnecessary and should be treated as * deprecated. Instead, use the {@code HashMap} constructor directly, taking advantage of the new * "diamond" syntax. * * @return a new, empty {@code HashMap} */ public static HashMap newHashMap() { return new HashMap<>(); } /** * Creates a mutable {@code HashMap} instance with the same mappings as the specified map. * *

Note: if mutability is not required, use {@link ImmutableMap#copyOf(Map)} instead. * *

Note: if {@code K} is an {@link Enum} type, use {@link #newEnumMap} instead. * *

Note for Java 7 and later: this method is now unnecessary and should be treated as * deprecated. Instead, use the {@code HashMap} constructor directly, taking advantage of the new * "diamond" syntax. * * @param map the mappings to be placed in the new map * @return a new {@code HashMap} initialized with the mappings from {@code map} */ public static HashMap newHashMap(Map map) { return new HashMap<>(map); } /** * Creates a {@code HashMap} instance, with a high enough "initial capacity" that it should * hold {@code expectedSize} elements without growth. This behavior cannot be broadly guaranteed, * but it is observed to be true for OpenJDK 1.7. It also can't be guaranteed that the method * isn't inadvertently oversizing the returned map. * * @param expectedSize the number of entries you expect to add to the returned map * @return a new, empty {@code HashMap} with enough capacity to hold {@code expectedSize} entries * without resizing * @throws IllegalArgumentException if {@code expectedSize} is negative */ public static HashMap newHashMapWithExpectedSize(int expectedSize) { return new HashMap<>(capacity(expectedSize)); } /** * Returns a capacity that is sufficient to keep the map from being resized as long as it grows no * larger than expectedSize and the load factor is ≥ its default (0.75). */ static int capacity(int expectedSize) { if (expectedSize < 3) { // checkNonnegative(expectedSize, "expectedSize"); return expectedSize + 1; } if (expectedSize < Ints.MAX_POWER_OF_TWO) { // This is the calculation used in JDK8 to resize when a putAll // happens; it seems to be the most conservative calculation we // can make. 0.75 is the default load factor. return (int) ((float) expectedSize / 0.75F + 1.0F); } return Integer.MAX_VALUE; // any large value } /** * Creates a mutable, empty, insertion-ordered {@code LinkedHashMap} instance. * *

Note: if mutability is not required, use {@link ImmutableMap#of()} instead. * *

Note for Java 7 and later: this method is now unnecessary and should be treated as * deprecated. Instead, use the {@code LinkedHashMap} constructor directly, taking advantage of * the new "diamond" syntax. * * @return a new, empty {@code LinkedHashMap} */ public static LinkedHashMap newLinkedHashMap() { return new LinkedHashMap<>(); } /** * Creates a mutable, insertion-ordered {@code LinkedHashMap} instance with the same * mappings as the specified map. * *

Note: if mutability is not required, use {@link ImmutableMap#copyOf(Map)} instead. * *

Note for Java 7 and later: this method is now unnecessary and should be treated as * deprecated. Instead, use the {@code LinkedHashMap} constructor directly, taking advantage of * the new "diamond" syntax. * * @param map the mappings to be placed in the new map * @return a new, {@code LinkedHashMap} initialized with the mappings from {@code map} */ public static LinkedHashMap newLinkedHashMap(Map map) { return new LinkedHashMap<>(map); } /** * Creates a {@code LinkedHashMap} instance, with a high enough "initial capacity" that it * should hold {@code expectedSize} elements without growth. This behavior cannot be * broadly guaranteed, but it is observed to be true for OpenJDK 1.7. It also can't be guaranteed * that the method isn't inadvertently oversizing the returned map. * * @param expectedSize the number of entries you expect to add to the returned map * @return a new, empty {@code LinkedHashMap} with enough capacity to hold {@code expectedSize} * entries without resizing * @throws IllegalArgumentException if {@code expectedSize} is negative * @since 19.0 */ public static LinkedHashMap newLinkedHashMapWithExpectedSize(int expectedSize) { return new LinkedHashMap<>(capacity(expectedSize)); } /** * Creates a new empty {@link ConcurrentHashMap} instance. * * @since 3.0 */ public static ConcurrentMap newConcurrentMap() { return new ConcurrentHashMap<>(); } /** * Creates a mutable, empty {@code TreeMap} instance using the natural ordering of its * elements. * *

Note: if mutability is not required, use {@link ImmutableSortedMap#of()} instead. * *

Note for Java 7 and later: this method is now unnecessary and should be treated as * deprecated. Instead, use the {@code TreeMap} constructor directly, taking advantage of the new * "diamond" syntax. * * @return a new, empty {@code TreeMap} */ public static TreeMap newTreeMap() { return new TreeMap<>(); } /** * Creates a mutable {@code TreeMap} instance with the same mappings as the specified map * and using the same ordering as the specified map. * *

Note: if mutability is not required, use {@link * ImmutableSortedMap#copyOfSorted(SortedMap)} instead. * *

Note for Java 7 and later: this method is now unnecessary and should be treated as * deprecated. Instead, use the {@code TreeMap} constructor directly, taking advantage of the new * "diamond" syntax. * * @param map the sorted map whose mappings are to be placed in the new map and whose comparator * is to be used to sort the new map * @return a new {@code TreeMap} initialized with the mappings from {@code map} and using the * comparator of {@code map} */ public static TreeMap newTreeMap(SortedMap map) { return new TreeMap<>(map); } /** * Creates a mutable, empty {@code TreeMap} instance using the given comparator. * *

Note: if mutability is not required, use {@code * ImmutableSortedMap.orderedBy(comparator).build()} instead. * *

Note for Java 7 and later: this method is now unnecessary and should be treated as * deprecated. Instead, use the {@code TreeMap} constructor directly, taking advantage of the new * "diamond" syntax. * * @param comparator the comparator to sort the keys with * @return a new, empty {@code TreeMap} */ public static TreeMap newTreeMap(@Nullable Comparator comparator) { // Ideally, the extra type parameter "C" shouldn't be necessary. It is a // work-around of a compiler type inference quirk that prevents the // following code from being compiled: // Comparator> comparator = null; // Map, String> map = newTreeMap(comparator); return new TreeMap<>(comparator); } /** * Creates an {@code EnumMap} instance. * * @param type the key type for this map * @return a new, empty {@code EnumMap} */ public static , V> EnumMap newEnumMap(Class type) { return new EnumMap<>(checkNotNull(type)); } /** * Creates an {@code EnumMap} with the same mappings as the specified map. * *

Note for Java 7 and later: this method is now unnecessary and should be treated as * deprecated. Instead, use the {@code EnumMap} constructor directly, taking advantage of the new * "diamond" syntax. * * @param map the map from which to initialize this {@code EnumMap} * @return a new {@code EnumMap} initialized with the mappings from {@code map} * @throws IllegalArgumentException if {@code m} is not an {@code EnumMap} instance and contains * no mappings */ public static , V> EnumMap newEnumMap(Map map) { return new EnumMap<>(map); } /** * Creates an {@code IdentityHashMap} instance. * *

Note for Java 7 and later: this method is now unnecessary and should be treated as * deprecated. Instead, use the {@code IdentityHashMap} constructor directly, taking advantage of * the new "diamond" syntax. * * @return a new, empty {@code IdentityHashMap} */ public static IdentityHashMap newIdentityHashMap() { return new IdentityHashMap<>(); } // /** // * 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. // * // *

Since this method uses {@code HashMap} instances internally, the keys of the supplied maps // * must be well-behaved with respect to {@link Object#equals} and {@link Object#hashCode}. // * // *

Note:If you only need to know whether two maps have the same mappings, call {@code // * left.equals(right)} instead of this method. // * // * @param left the map to treat as the "left" map for purposes of comparison // * @param right the map to treat as the "right" map for purposes of comparison // * @return the difference between the two maps // */ // @SuppressWarnings("unchecked") // public static MapDifference difference( // Map left, Map right) { // if (left instanceof SortedMap) { // SortedMap sortedLeft = (SortedMap) left; // return difference(sortedLeft, right); // } // return difference(left, right, Equivalence.equals()); // } // // /** // * 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. // * // *

Since this method uses {@code HashMap} instances internally, the keys of the supplied maps // * must be well-behaved with respect to {@link Object#equals} and {@link Object#hashCode}. // * // * @param left the map to treat as the "left" map for purposes of comparison // * @param right the map to treat as the "right" map for purposes of comparison // * @param valueEquivalence the equivalence relationship to use to compare values // * @return the difference between the two maps // * @since 10.0 // */ // public static MapDifference difference( // Map left, // Map right, // Equivalence valueEquivalence) { // Preconditions.checkNotNull(valueEquivalence); // // Map onlyOnLeft = newLinkedHashMap(); // Map onlyOnRight = new LinkedHashMap<>(right); // will whittle it down // Map onBoth = newLinkedHashMap(); // Map> differences = newLinkedHashMap(); // doDifference(left, right, valueEquivalence, onlyOnLeft, onlyOnRight, onBoth, differences); // return new MapDifferenceImpl<>(onlyOnLeft, onlyOnRight, onBoth, differences); // } // // /** // * Computes the difference between two sorted maps, using the comparator of the left map, or // * {@code Ordering.natural()} if the left map uses the natural ordering of its elements. 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. // * // *

Since this method uses {@code TreeMap} instances internally, the keys of the right map must // * all compare as distinct according to the comparator of the left map. // * // *

Note:If you only need to know whether two sorted maps have the same mappings, call // * {@code left.equals(right)} instead of this method. // * // * @param left the map to treat as the "left" map for purposes of comparison // * @param right the map to treat as the "right" map for purposes of comparison // * @return the difference between the two maps // * @since 11.0 // */ // public static SortedMapDifference difference( // SortedMap left, Map right) { // checkNotNull(left); // checkNotNull(right); // Comparator comparator = orNaturalOrder(left.comparator()); // SortedMap onlyOnLeft = Maps.newTreeMap(comparator); // SortedMap onlyOnRight = Maps.newTreeMap(comparator); // onlyOnRight.putAll(right); // will whittle it down // SortedMap onBoth = Maps.newTreeMap(comparator); // SortedMap> differences = Maps.newTreeMap(comparator); // doDifference(left, right, Equivalence.equals(), onlyOnLeft, onlyOnRight, onBoth, differences); // return new SortedMapDifferenceImpl<>(onlyOnLeft, onlyOnRight, onBoth, differences); // } // // private static void doDifference( // Map left, // Map right, // Equivalence valueEquivalence, // Map onlyOnLeft, // Map onlyOnRight, // Map onBoth, // Map> differences) { // for (Entry entry : left.entrySet()) { // K leftKey = entry.getKey(); // V leftValue = entry.getValue(); // if (right.containsKey(leftKey)) { // V rightValue = onlyOnRight.remove(leftKey); // if (valueEquivalence.equivalent(leftValue, rightValue)) { // onBoth.put(leftKey, leftValue); // } else { // differences.put(leftKey, ValueDifferenceImpl.create(leftValue, rightValue)); // } // } else { // onlyOnLeft.put(leftKey, leftValue); // } // } // } // // private static Map unmodifiableMap(Map map) { // if (map instanceof SortedMap) { // return Collections.unmodifiableSortedMap((SortedMap) map); // } else { // return Collections.unmodifiableMap(map); // } // } // // static class MapDifferenceImpl implements MapDifference { // final Map onlyOnLeft; // final Map onlyOnRight; // final Map onBoth; // final Map> differences; // // MapDifferenceImpl( // Map onlyOnLeft, // Map onlyOnRight, // Map onBoth, // Map> differences) { // this.onlyOnLeft = unmodifiableMap(onlyOnLeft); // this.onlyOnRight = unmodifiableMap(onlyOnRight); // this.onBoth = unmodifiableMap(onBoth); // this.differences = unmodifiableMap(differences); // } // // @Override // public boolean areEqual() { // return onlyOnLeft.isEmpty() && onlyOnRight.isEmpty() && differences.isEmpty(); // } // // @Override // public Map entriesOnlyOnLeft() { // return onlyOnLeft; // } // // @Override // public Map entriesOnlyOnRight() { // return onlyOnRight; // } // // @Override // public Map entriesInCommon() { // return onBoth; // } // // @Override // public Map> entriesDiffering() { // return differences; // } // // @Override // public boolean equals(Object object) { // if (object == this) { // return true; // } // if (object instanceof MapDifference) { // MapDifference other = (MapDifference) object; // return entriesOnlyOnLeft().equals(other.entriesOnlyOnLeft()) // && entriesOnlyOnRight().equals(other.entriesOnlyOnRight()) // && entriesInCommon().equals(other.entriesInCommon()) // && entriesDiffering().equals(other.entriesDiffering()); // } // return false; // } // // @Override // public int hashCode() { // return Objects.hashCode( // entriesOnlyOnLeft(), entriesOnlyOnRight(), entriesInCommon(), entriesDiffering()); // } // // @Override // public String toString() { // if (areEqual()) { // return "equal"; // } // // StringBuilder result = new StringBuilder("not equal"); // if (!onlyOnLeft.isEmpty()) { // result.append(": only on left=").append(onlyOnLeft); // } // if (!onlyOnRight.isEmpty()) { // result.append(": only on right=").append(onlyOnRight); // } // if (!differences.isEmpty()) { // result.append(": value differences=").append(differences); // } // return result.toString(); // } // } // // static class ValueDifferenceImpl implements MapDifference.ValueDifference { // private final @Nullable V left; // private final @Nullable V right; // // static ValueDifference create(@Nullable V left, @Nullable V right) { // return new ValueDifferenceImpl(left, right); // } // // private ValueDifferenceImpl(@Nullable V left, @Nullable V right) { // this.left = left; // this.right = right; // } // // @Override // public V leftValue() { // return left; // } // // @Override // public V rightValue() { // return right; // } // // @Override // public boolean equals(@Nullable Object object) { // if (object instanceof MapDifference.ValueDifference) { // MapDifference.ValueDifference that = (MapDifference.ValueDifference) object; // return Objects.equal(this.left, that.leftValue()) // && Objects.equal(this.right, that.rightValue()); // } // return false; // } // // @Override // public int hashCode() { // return Objects.hashCode(left, right); // } // // @Override // public String toString() { // return "(" + left + ", " + right + ")"; // } // } // // static class SortedMapDifferenceImpl extends MapDifferenceImpl // implements SortedMapDifference { // SortedMapDifferenceImpl( // SortedMap onlyOnLeft, // SortedMap onlyOnRight, // SortedMap onBoth, // SortedMap> differences) { // super(onlyOnLeft, onlyOnRight, onBoth, differences); // } // // @Override // public SortedMap> entriesDiffering() { // return (SortedMap>) super.entriesDiffering(); // } // // @Override // public SortedMap entriesInCommon() { // return (SortedMap) super.entriesInCommon(); // } // // @Override // public SortedMap entriesOnlyOnLeft() { // return (SortedMap) super.entriesOnlyOnLeft(); // } // // @Override // public SortedMap entriesOnlyOnRight() { // return (SortedMap) super.entriesOnlyOnRight(); // } // } // // /** // * Returns the specified comparator if not null; otherwise returns {@code Ordering.natural()}. // * This method is an abomination of generics; the only purpose of this method is to contain the // * ugly type-casting in one place. // */ // @SuppressWarnings("unchecked") // static Comparator orNaturalOrder(@Nullable Comparator comparator) { // if (comparator != null) { // can't use ? : because of javac bug 5080917 // return comparator; // } // return (Comparator) Ordering.natural(); // } // // /** // * Returns a live {@link Map} view whose keys are the contents of {@code set} and whose values are // * computed on demand using {@code function}. To get an immutable copy instead, use {@link // * #toMap(Iterable, Function)}. // * // *

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. // * // *

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. // * // *

Warning: 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. // * // *

Warning: 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 // */ // public static Map asMap(Set set, Function function) { // return new AsMapView<>(set, function); // } // // /** // * Returns a view of the sorted set as a map, mapping keys from the set according to the specified // * function. // * // *

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. // * // *

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. // * // *

Warning: 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. // * // *

Warning: 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 // */ // public static SortedMap asMap(SortedSet set, Function function) { // return new SortedAsMapView<>(set, function); // } // // /** // * Returns a view of the navigable set as a map, mapping keys from the set according to the // * specified function. // * // *

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. // * // *

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. // * // *

Warning: 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. // * // *

Warning: 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 // */ // @GwtIncompatible // NavigableMap // public static NavigableMap asMap( // NavigableSet set, Function function) { // return new NavigableAsMapView<>(set, function); // } // // private static class AsMapView extends ViewCachingAbstractMap { // // private final Set set; // final Function function; // // Set backingSet() { // return set; // } // // AsMapView(Set set, Function function) { // this.set = checkNotNull(set); // this.function = checkNotNull(function); // } // // @Override // public Set createKeySet() { // return removeOnlySet(backingSet()); // } // // @Override // Collection createValues() { // 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) { // return getOrDefault(key, null); // } // // @Override // public V getOrDefault(@Nullable Object key, @Nullable V defaultValue) { // if (Collections2.safeContains(backingSet(), key)) { // @SuppressWarnings("unchecked") // unsafe, but Javadoc warns about it // K k = (K) key; // return function.apply(k); // } else { // return defaultValue; // } // } // // @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> createEntrySet() { // @WeakOuter // class EntrySetImpl extends EntrySet { // @Override // Map map() { // return AsMapView.this; // } // // @Override // public Iterator> iterator() { // return asMapEntryIterator(backingSet(), function); // } // } // return new EntrySetImpl(); // } // // @Override // public void forEach(BiConsumer action) { // checkNotNull(action); // // avoids allocation of entries // backingSet().forEach(k -> action.accept(k, function.apply(k))); // } // } // // static Iterator> asMapEntryIterator( // Set set, final Function function) { // return new TransformedIterator>(set.iterator()) { // @Override // Entry transform(final K key) { // return immutableEntry(key, function.apply(key)); // } // }; // } // // private static class SortedAsMapView extends AsMapView implements SortedMap { // // SortedAsMapView(SortedSet set, Function function) { // super(set, function); // } // // @Override // SortedSet backingSet() { // return (SortedSet) super.backingSet(); // } // // @Override // public Comparator comparator() { // return backingSet().comparator(); // } // // @Override // public Set keySet() { // return removeOnlySortedSet(backingSet()); // } // // @Override // public SortedMap subMap(K fromKey, K toKey) { // return asMap(backingSet().subSet(fromKey, toKey), function); // } // // @Override // public SortedMap headMap(K toKey) { // return asMap(backingSet().headSet(toKey), function); // } // // @Override // public SortedMap 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 extends AbstractNavigableMap { // /* // * Using AbstractNavigableMap is simpler than extending SortedAsMapView and rewriting all the // * NavigableMap methods. // */ // // private final NavigableSet set; // private final Function function; // // NavigableAsMapView(NavigableSet ks, Function vFunction) { // this.set = checkNotNull(ks); // this.function = checkNotNull(vFunction); // } // // @Override // public NavigableMap subMap( // K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { // return asMap(set.subSet(fromKey, fromInclusive, toKey, toInclusive), function); // } // // @Override // public NavigableMap headMap(K toKey, boolean inclusive) { // return asMap(set.headSet(toKey, inclusive), function); // } // // @Override // public NavigableMap tailMap(K fromKey, boolean inclusive) { // return asMap(set.tailSet(fromKey, inclusive), function); // } // // @Override // public Comparator comparator() { // return set.comparator(); // } // // @Override // public @Nullable V get(@Nullable Object key) { // return getOrDefault(key, null); // } // // @Override // public @Nullable V getOrDefault(@Nullable Object key, @Nullable V defaultValue) { // if (Collections2.safeContains(set, key)) { // @SuppressWarnings("unchecked") // unsafe, but Javadoc warns about it // K k = (K) key; // return function.apply(k); // } else { // return defaultValue; // } // } // // @Override // public void clear() { // set.clear(); // } // // @Override // Iterator> entryIterator() { // return asMapEntryIterator(set, function); // } // // @Override // Spliterator> entrySpliterator() { // return CollectSpliterators.map(set.spliterator(), e -> immutableEntry(e, function.apply(e))); // } // // @Override // public void forEach(BiConsumer action) { // set.forEach(k -> action.accept(k, function.apply(k))); // } // // @Override // Iterator> descendingEntryIterator() { // return descendingMap().entrySet().iterator(); // } // // @Override // public NavigableSet navigableKeySet() { // return removeOnlyNavigableSet(set); // } // // @Override // public int size() { // return set.size(); // } // // @Override // public NavigableMap descendingMap() { // return asMap(set.descendingSet(), function); // } // } // // private static Set removeOnlySet(final Set set) { // return new ForwardingSet() { // @Override // protected Set delegate() { // return set; // } // // @Override // public boolean add(E element) { // throw new UnsupportedOperationException(); // } // // @Override // public boolean addAll(Collection es) { // throw new UnsupportedOperationException(); // } // }; // } // // private static SortedSet removeOnlySortedSet(final SortedSet set) { // return new ForwardingSortedSet() { // @Override // protected SortedSet delegate() { // return set; // } // // @Override // public boolean add(E element) { // throw new UnsupportedOperationException(); // } // // @Override // public boolean addAll(Collection es) { // throw new UnsupportedOperationException(); // } // // @Override // public SortedSet headSet(E toElement) { // return removeOnlySortedSet(super.headSet(toElement)); // } // // @Override // public SortedSet subSet(E fromElement, E toElement) { // return removeOnlySortedSet(super.subSet(fromElement, toElement)); // } // // @Override // public SortedSet tailSet(E fromElement) { // return removeOnlySortedSet(super.tailSet(fromElement)); // } // }; // } // // @GwtIncompatible // NavigableSet // private static NavigableSet removeOnlyNavigableSet(final NavigableSet set) { // return new ForwardingNavigableSet() { // @Override // protected NavigableSet delegate() { // return set; // } // // @Override // public boolean add(E element) { // throw new UnsupportedOperationException(); // } // // @Override // public boolean addAll(Collection es) { // throw new UnsupportedOperationException(); // } // // @Override // public SortedSet headSet(E toElement) { // return removeOnlySortedSet(super.headSet(toElement)); // } // // @Override // public NavigableSet headSet(E toElement, boolean inclusive) { // return removeOnlyNavigableSet(super.headSet(toElement, inclusive)); // } // // @Override // public SortedSet subSet(E fromElement, E toElement) { // return removeOnlySortedSet(super.subSet(fromElement, toElement)); // } // // @Override // public NavigableSet subSet( // E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { // return removeOnlyNavigableSet( // super.subSet(fromElement, fromInclusive, toElement, toInclusive)); // } // // @Override // public SortedSet tailSet(E fromElement) { // return removeOnlySortedSet(super.tailSet(fromElement)); // } // // @Override // public NavigableSet tailSet(E fromElement, boolean inclusive) { // return removeOnlyNavigableSet(super.tailSet(fromElement, inclusive)); // } // // @Override // public NavigableSet descendingSet() { // return removeOnlyNavigableSet(super.descendingSet()); // } // }; // } // // /** // * Returns an immutable map whose keys are the distinct elements of {@code keys} and whose value // * for each key was computed by {@code valueFunction}. The map's iteration order is the order of // * the first appearance of each key in {@code keys}. // * // *

When there are multiple instances of a key in {@code keys}, it is unspecified whether {@code // * valueFunction} will be applied to more than one instance of that key and, if it is, which // * result will be mapped to that key in the returned map. // * // *

If {@code keys} is a {@link Set}, a live view can be obtained instead of a copy using {@link // * Maps#asMap(Set, Function)}. // * // * @throws NullPointerException if any element of {@code keys} is {@code null}, or if {@code // * valueFunction} produces {@code null} for any key // * @since 14.0 // */ // public static ImmutableMap toMap( // Iterable keys, Function valueFunction) { // return toMap(keys.iterator(), valueFunction); // } // // /** // * Returns an immutable map whose keys are the distinct elements of {@code keys} and whose value // * for each key was computed by {@code valueFunction}. The map's iteration order is the order of // * the first appearance of each key in {@code keys}. // * // *

When there are multiple instances of a key in {@code keys}, it is unspecified whether {@code // * valueFunction} will be applied to more than one instance of that key and, if it is, which // * result will be mapped to that key in the returned map. // * // * @throws NullPointerException if any element of {@code keys} is {@code null}, or if {@code // * valueFunction} produces {@code null} for any key // * @since 14.0 // */ // public static ImmutableMap toMap( // Iterator keys, Function valueFunction) { // checkNotNull(valueFunction); // // Using LHM instead of a builder so as not to fail on duplicate keys // Map builder = newLinkedHashMap(); // while (keys.hasNext()) { // K key = keys.next(); // builder.put(key, valueFunction.apply(key)); // } // return ImmutableMap.copyOf(builder); // } // // /** // * Returns a map with the given {@code values}, indexed by keys derived from those values. In // * other words, each input value produces an entry in the map whose key is the result of applying // * {@code keyFunction} to that value. These entries appear in the same order as the input values. // * Example usage: // * // *

{@code
//   * Color red = new Color("red", 255, 0, 0);
//   * ...
//   * ImmutableSet allColors = ImmutableSet.of(red, green, blue);
//   *
//   * Map colorForName =
//   *     uniqueIndex(allColors, toStringFunction());
//   * assertThat(colorForName).containsEntry("red", red);
//   * }
// * // *

If your index may associate multiple values with each key, use {@link // * Multimaps#index(Iterable, Function) Multimaps.index}. // * // * @param values the values to use when constructing the {@code Map} // * @param keyFunction the function used to produce the key for each value // * @return a map mapping the result of evaluating the function {@code keyFunction} on each value // * in the input collection to that value // * @throws IllegalArgumentException if {@code keyFunction} produces the same key for more than one // * value in the input collection // * @throws NullPointerException if any element of {@code values} is {@code null}, or if {@code // * keyFunction} produces {@code null} for any value // */ // @CanIgnoreReturnValue // public static ImmutableMap uniqueIndex( // Iterable values, Function keyFunction) { // // TODO(lowasser): consider presizing the builder if values is a Collection // return uniqueIndex(values.iterator(), keyFunction); // } // // /** // * Returns a map with the given {@code values}, indexed by keys derived from those values. In // * other words, each input value produces an entry in the map whose key is the result of applying // * {@code keyFunction} to that value. These entries appear in the same order as the input values. // * Example usage: // * // *

{@code
//   * Color red = new Color("red", 255, 0, 0);
//   * ...
//   * Iterator allColors = ImmutableSet.of(red, green, blue).iterator();
//   *
//   * Map colorForName =
//   *     uniqueIndex(allColors, toStringFunction());
//   * assertThat(colorForName).containsEntry("red", red);
//   * }
// * // *

If your index may associate multiple values with each key, use {@link // * Multimaps#index(Iterator, Function) Multimaps.index}. // * // * @param values the values to use when constructing the {@code Map} // * @param keyFunction the function used to produce the key for each value // * @return a map mapping the result of evaluating the function {@code keyFunction} on each value // * in the input collection to that value // * @throws IllegalArgumentException if {@code keyFunction} produces the same key for more than one // * value in the input collection // * @throws NullPointerException if any element of {@code values} is {@code null}, or if {@code // * keyFunction} produces {@code null} for any value // * @since 10.0 // */ // @CanIgnoreReturnValue // public static ImmutableMap uniqueIndex( // Iterator values, Function keyFunction) { // checkNotNull(keyFunction); // ImmutableMap.Builder builder = ImmutableMap.builder(); // while (values.hasNext()) { // V value = values.next(); // builder.put(keyFunction.apply(value), value); // } // try { // return builder.build(); // } catch (IllegalArgumentException duplicateKeys) { // throw new IllegalArgumentException( // duplicateKeys.getMessage() // + ". To index multiple values under a key, use Multimaps.index."); // } // } // // /** // * Creates an {@code ImmutableMap} from a {@code Properties} instance. Properties // * normally derive from {@code Map}, but they typically contain strings, which is // * awkward. This method lets you get a plain-old-{@code Map} out of a {@code Properties}. // * // * @param properties a {@code Properties} object to be converted // * @return an immutable map containing all the entries in {@code properties} // * @throws ClassCastException if any key in {@code Properties} is not a {@code String} // * @throws NullPointerException if any key or value in {@code Properties} is null // */ // @GwtIncompatible // java.util.Properties // public static ImmutableMap fromProperties(Properties properties) { // ImmutableMap.Builder builder = ImmutableMap.builder(); // // for (Enumeration e = properties.propertyNames(); e.hasMoreElements(); ) { // String key = (String) e.nextElement(); // builder.put(key, properties.getProperty(key)); // } // // return builder.build(); // } // /** * Returns an immutable map entry with the specified key and value. The {@link Entry#setValue} * operation throws an {@link UnsupportedOperationException}. * *

The returned entry is serializable. * *

Java 9 users: consider using {@code java.util.Map.entry(key, value)} if the key and * value are non-null and the entry does not need to be serializable. * * @param key the key to be associated with the returned entry * @param value the value to be associated with the returned entry */ @GwtCompatible(serializable = true) public static Entry immutableEntry(@Nullable K key, @Nullable V value) { return new ImmutableEntry<>(key, value); } // // /** // * Returns an unmodifiable view of the specified set of entries. The {@link Entry#setValue} // * operation throws an {@link UnsupportedOperationException}, as do any operations that would // * modify the returned set. // * // * @param entrySet the entries for which to return an unmodifiable view // * @return an unmodifiable view of the entries // */ // static Set> unmodifiableEntrySet(Set> entrySet) { // return new UnmodifiableEntrySet<>(Collections.unmodifiableSet(entrySet)); // } // // /** // * Returns an unmodifiable view of the specified map entry. The {@link Entry#setValue} operation // * throws an {@link UnsupportedOperationException}. This also has the side-effect of redefining // * {@code equals} to comply with the Entry contract, to avoid a possible nefarious implementation // * of equals. // * // * @param entry the entry for which to return an unmodifiable view // * @return an unmodifiable view of the entry // */ // static Entry unmodifiableEntry(final Entry entry) { // checkNotNull(entry); // return new AbstractMapEntry() { // @Override // public K getKey() { // return entry.getKey(); // } // // @Override // public V getValue() { // return entry.getValue(); // } // }; // } // // static UnmodifiableIterator> unmodifiableEntryIterator( // final Iterator> entryIterator) { // return new UnmodifiableIterator>() { // @Override // public boolean hasNext() { // return entryIterator.hasNext(); // } // // @Override // public Entry next() { // return unmodifiableEntry(entryIterator.next()); // } // }; // } // // /** @see Multimaps#unmodifiableEntries */ // static class UnmodifiableEntries extends ForwardingCollection> { // private final Collection> entries; // // UnmodifiableEntries(Collection> entries) { // this.entries = entries; // } // // @Override // protected Collection> delegate() { // return entries; // } // // @Override // public Iterator> iterator() { // return unmodifiableEntryIterator(entries.iterator()); // } // // // See java.util.Collections.UnmodifiableEntrySet for details on attacks. // // @Override // public Object[] toArray() { // return standardToArray(); // } // // @Override // public T[] toArray(T[] array) { // return standardToArray(array); // } // } // // /** @see Maps#unmodifiableEntrySet(Set) */ // static class UnmodifiableEntrySet extends UnmodifiableEntries // implements Set> { // UnmodifiableEntrySet(Set> entries) { // super(entries); // } // // // See java.util.Collections.UnmodifiableEntrySet for details on attacks. // // @Override // public boolean equals(@Nullable Object object) { // return Sets.equalsImpl(this, object); // } // // @Override // public int hashCode() { // return Sets.hashCodeImpl(this); // } // } // // /** // * Returns a {@link Converter} that converts values using {@link BiMap#get bimap.get()}, and whose // * inverse view converts values using {@link BiMap#inverse bimap.inverse()}{@code .get()}. // * // *

To use a plain {@link Map} as a {@link Function}, see {@link // * org.docx4j.com.google.common.base.Functions#forMap(Map)} or {@link // * org.docx4j.com.google.common.base.Functions#forMap(Map, Object)}. // * // * @since 16.0 // */ // public static Converter asConverter(final BiMap bimap) { // return new BiMapConverter<>(bimap); // } // // private static final class BiMapConverter extends Converter implements Serializable { // private final BiMap bimap; // // BiMapConverter(BiMap bimap) { // this.bimap = checkNotNull(bimap); // } // // @Override // protected B doForward(A a) { // return convert(bimap, a); // } // // @Override // protected A doBackward(B b) { // return convert(bimap.inverse(), b); // } // // private static Y convert(BiMap bimap, X input) { // Y output = bimap.get(input); // checkArgument(output != null, "No non-null mapping present for input: %s", input); // return output; // } // // @Override // public boolean equals(@Nullable Object object) { // if (object instanceof BiMapConverter) { // BiMapConverter that = (BiMapConverter) object; // return this.bimap.equals(that.bimap); // } // return false; // } // // @Override // public int hashCode() { // return bimap.hashCode(); // } // // // There's really no good way to implement toString() without printing the entire BiMap, right? // @Override // public String toString() { // return "Maps.asConverter(" + bimap + ")"; // } // // private static final long serialVersionUID = 0L; // } // // /** // * Returns a synchronized (thread-safe) bimap backed by the specified bimap. In order to guarantee // * serial access, it is critical that all access to the backing bimap is accomplished // * through the returned bimap. // * // *

It is imperative that the user manually synchronize on the returned map when accessing any // * of its collection views: // * // *

{@code
//   * BiMap map = Maps.synchronizedBiMap(
//   *     HashBiMap.create());
//   * ...
//   * Set set = map.keySet();  // Needn't be in synchronized block
//   * ...
//   * synchronized (map) {  // Synchronizing on map, not set!
//   *   Iterator it = set.iterator(); // Must be in synchronized block
//   *   while (it.hasNext()) {
//   *     foo(it.next());
//   *   }
//   * }
//   * }
// * // *

Failure to follow this advice may result in non-deterministic behavior. // * // *

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 synchronized view of the specified bimap // */ // public static BiMap synchronizedBiMap(BiMap 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 attempts to modify the returned map, whether direct or via // * its collection views, result in an {@code UnsupportedOperationException}. // * // *

The returned bimap will be serializable if the specified bimap is serializable. // * // * @param bimap the bimap for which an unmodifiable view is to be returned // * @return an unmodifiable view of the specified bimap // */ // public static BiMap unmodifiableBiMap(BiMap bimap) { // return new UnmodifiableBiMap<>(bimap, null); // } // // /** @see Maps#unmodifiableBiMap(BiMap) */ // private static class UnmodifiableBiMap extends ForwardingMap // implements BiMap, Serializable { // final Map unmodifiableMap; // final BiMap delegate; // @MonotonicNonNull @RetainedWith BiMap inverse; // @MonotonicNonNull transient Set values; // // UnmodifiableBiMap(BiMap delegate, @Nullable BiMap inverse) { // unmodifiableMap = Collections.unmodifiableMap(delegate); // this.delegate = delegate; // this.inverse = inverse; // } // // @Override // protected Map delegate() { // return unmodifiableMap; // } // // @Override // public V forcePut(K key, V value) { // throw new UnsupportedOperationException(); // } // // @Override // public BiMap inverse() { // BiMap result = inverse; // return (result == null) // ? inverse = new UnmodifiableBiMap<>(delegate.inverse(), this) // : result; // } // // @Override // public Set values() { // Set result = values; // return (result == null) ? values = Collections.unmodifiableSet(delegate.values()) : result; // } // // private static final long serialVersionUID = 0; // } // // /** // * Returns a view of a 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: // * // *

{@code
//   * Map map = ImmutableMap.of("a", 4, "b", 9);
//   * Function sqrt =
//   *     new Function() {
//   *       public Double apply(Integer in) {
//   *         return Math.sqrt((int) in);
//   *       }
//   *     };
//   * Map transformed = Maps.transformValues(map, sqrt);
//   * System.out.println(transformed);
//   * }
// * // * ... 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. // * // *

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. // * // *

The returned map is not thread-safe or serializable, even if the underlying map is. // * // *

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. // */ // public static Map transformValues( // Map fromMap, Function function) { // return transformEntries(fromMap, asEntryTransformer(function)); // } // // /** // * Returns a view of a sorted 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: // * // *

{@code
//   * SortedMap map = ImmutableSortedMap.of("a", 4, "b", 9);
//   * Function sqrt =
//   *     new Function() {
//   *       public Double apply(Integer in) {
//   *         return Math.sqrt((int) in);
//   *       }
//   *     };
//   * SortedMap transformed =
//   *      Maps.transformValues(map, sqrt);
//   * System.out.println(transformed);
//   * }
// * // * ... 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. // * // *

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. // * // *

The returned map is not thread-safe or serializable, even if the underlying map is. // * // *

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 11.0 // */ // public static SortedMap transformValues( // SortedMap fromMap, Function 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: // * // *

{@code
//   * NavigableMap map = Maps.newTreeMap();
//   * map.put("a", 4);
//   * map.put("b", 9);
//   * Function sqrt =
//   *     new Function() {
//   *       public Double apply(Integer in) {
//   *         return Math.sqrt((int) in);
//   *       }
//   *     };
//   * NavigableMap transformed =
//   *      Maps.transformNavigableValues(map, sqrt);
//   * System.out.println(transformed);
//   * }
// * // * ... 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. // * // *

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. // * // *

The returned map is not thread-safe or serializable, even if the underlying map is. // * // *

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 NavigableMap transformValues( // NavigableMap fromMap, Function function) { // return transformEntries(fromMap, asEntryTransformer(function)); // } // // /** // * Returns a view of a map whose values are derived from the original map's entries. In contrast // * to {@link #transformValues}, this method's entry-transformation logic may depend on the key as // * well as the value. // * // *

All other properties of the transformed map, such as iteration order, are left intact. For // * example, the code: // * // *

{@code
//   * Map options =
//   *     ImmutableMap.of("verbose", true, "sort", false);
//   * EntryTransformer flagPrefixer =
//   *     new EntryTransformer() {
//   *       public String transformEntry(String key, Boolean value) {
//   *         return value ? key : "no" + key;
//   *       }
//   *     };
//   * Map transformed =
//   *     Maps.transformEntries(options, flagPrefixer);
//   * System.out.println(transformed);
//   * }
// * // * ... prints {@code {verbose=verbose, sort=nosort}}. // * // *

Changes in the underlying map are reflected in this view. Conversely, this view supports // * removal operations, and these are reflected in the underlying map. // * // *

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. // * // *

The returned map is not thread-safe or serializable, even if the underlying map is. // * // *

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. // * // *

Warning: 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 7.0 // */ // public static Map transformEntries( // Map fromMap, EntryTransformer transformer) { // return new TransformedEntriesMap<>(fromMap, transformer); // } // // /** // * Returns a view of a sorted map whose values are derived from the original sorted map's entries. // * In contrast to {@link #transformValues}, this method's entry-transformation logic may depend on // * the key as well as the value. // * // *

All other properties of the transformed map, such as iteration order, are left intact. For // * example, the code: // * // *

{@code
//   * Map options =
//   *     ImmutableSortedMap.of("verbose", true, "sort", false);
//   * EntryTransformer flagPrefixer =
//   *     new EntryTransformer() {
//   *       public String transformEntry(String key, Boolean value) {
//   *         return value ? key : "yes" + key;
//   *       }
//   *     };
//   * SortedMap transformed =
//   *     Maps.transformEntries(options, flagPrefixer);
//   * System.out.println(transformed);
//   * }
// * // * ... prints {@code {sort=yessort, verbose=verbose}}. // * // *

Changes in the underlying map are reflected in this view. Conversely, this view supports // * removal operations, and these are reflected in the underlying map. // * // *

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. // * // *

The returned map is not thread-safe or serializable, even if the underlying map is. // * // *

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. // * // *

Warning: 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 11.0 // */ // public static SortedMap transformEntries( // SortedMap fromMap, EntryTransformer transformer) { // return new TransformedEntriesSortedMap<>(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. // * // *

All other properties of the transformed map, such as iteration order, are left intact. For // * example, the code: // * // *

{@code
//   * NavigableMap options = Maps.newTreeMap();
//   * options.put("verbose", false);
//   * options.put("sort", true);
//   * EntryTransformer flagPrefixer =
//   *     new EntryTransformer() {
//   *       public String transformEntry(String key, Boolean value) {
//   *         return value ? key : ("yes" + key);
//   *       }
//   *     };
//   * NavigableMap transformed =
//   *     LabsMaps.transformNavigableEntries(options, flagPrefixer);
//   * System.out.println(transformed);
//   * }
// * // * ... prints {@code {sort=yessort, verbose=verbose}}. // * // *

Changes in the underlying map are reflected in this view. Conversely, this view supports // * removal operations, and these are reflected in the underlying map. // * // *

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. // * // *

The returned map is not thread-safe or serializable, even if the underlying map is. // * // *

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. // * // *

Warning: 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 NavigableMap transformEntries( // final NavigableMap fromMap, EntryTransformer transformer) { // return new TransformedEntriesNavigableMap<>(fromMap, transformer); // } /** * A transformation of the value of a key-value pair, using both key and value as inputs. To apply * the transformation to a map, use {@link Maps#transformEntries(Map, EntryTransformer)}. * * @param the key type of the input and output entries * @param the value type of the input entry * @param the value type of the output entry * @since 7.0 */ @FunctionalInterface public interface EntryTransformer { /** * Determines an output value based on a key-value pair. This method is generally * expected, but not absolutely required, to have the following properties: * *

    *
  • Its execution does not cause any observable side effects. *
  • The computation is consistent with equals; that is, {@link Objects#equal * Objects.equal}{@code (k1, k2) &&} {@link Objects#equal}{@code (v1, v2)} implies that * {@code Objects.equal(transformer.transform(k1, v1), transformer.transform(k2, v2))}. *
* * @throws NullPointerException if the key or value is null and this transformer does not accept * null arguments */ V2 transformEntry(@Nullable K key, @Nullable V1 value); } /** Views a function as an entry transformer that ignores the entry key. */ static EntryTransformer asEntryTransformer( final Function function) { checkNotNull(function); return new EntryTransformer() { @Override public V2 transformEntry(K key, V1 value) { return function.apply(value); } }; } static Function asValueToValueFunction( final EntryTransformer transformer, final K key) { checkNotNull(transformer); return new Function() { @Override public V2 apply(@Nullable V1 v1) { return transformer.transformEntry(key, v1); } }; } /** Views an entry transformer as a function from {@code Entry} to values. */ static Function, V2> asEntryToValueFunction( final EntryTransformer transformer) { checkNotNull(transformer); return new Function, V2>() { @Override public V2 apply(Entry entry) { return transformer.transformEntry(entry.getKey(), entry.getValue()); } }; } // /** Returns a view of an entry transformed by the specified transformer. */ // static Entry transformEntry( // final EntryTransformer transformer, final Entry entry) { // checkNotNull(transformer); // checkNotNull(entry); // return new AbstractMapEntry() { // @Override // public K getKey() { // return entry.getKey(); // } // // @Override // public V2 getValue() { // return transformer.transformEntry(entry.getKey(), entry.getValue()); // } // }; // } // // /** Views an entry transformer as a function from entries to entries. */ // static Function, Entry> asEntryToEntryFunction( // final EntryTransformer transformer) { // checkNotNull(transformer); // return new Function, Entry>() { // @Override // public Entry apply(final Entry entry) { // return transformEntry(transformer, entry); // } // }; // } // // static class TransformedEntriesMap extends IteratorBasedAbstractMap { // final Map fromMap; // final EntryTransformer transformer; // // TransformedEntriesMap( // Map fromMap, EntryTransformer transformer) { // this.fromMap = checkNotNull(fromMap); // this.transformer = checkNotNull(transformer); // } // // @Override // public int size() { // return fromMap.size(); // } // // @Override // public boolean containsKey(Object key) { // return fromMap.containsKey(key); // } // // @Override // public @Nullable V2 get(@Nullable Object key) { // return getOrDefault(key, null); // } // // // safe as long as the user followed the Warning in the javadoc // @SuppressWarnings("unchecked") // @Override // public @Nullable V2 getOrDefault(@Nullable Object key, @Nullable V2 defaultValue) { // V1 value = fromMap.get(key); // return (value != null || fromMap.containsKey(key)) // ? transformer.transformEntry((K) key, value) // : defaultValue; // } // // // safe as long as the user followed the Warning in the javadoc // @SuppressWarnings("unchecked") // @Override // public V2 remove(Object key) { // return fromMap.containsKey(key) // ? transformer.transformEntry((K) key, fromMap.remove(key)) // : null; // } // // @Override // public void clear() { // fromMap.clear(); // } // // @Override // public Set keySet() { // return fromMap.keySet(); // } // // @Override // Iterator> entryIterator() { // return Iterators.transform( // fromMap.entrySet().iterator(), Maps.asEntryToEntryFunction(transformer)); // } // // @Override // Spliterator> entrySpliterator() { // return CollectSpliterators.map( // fromMap.entrySet().spliterator(), Maps.asEntryToEntryFunction(transformer)); // } // // @Override // public void forEach(BiConsumer action) { // checkNotNull(action); // // avoids creating new Entry objects // fromMap.forEach((k, v1) -> action.accept(k, transformer.transformEntry(k, v1))); // } // // @Override // public Collection values() { // return new Values<>(this); // } // } // // static class TransformedEntriesSortedMap extends TransformedEntriesMap // implements SortedMap { // // protected SortedMap fromMap() { // return (SortedMap) fromMap; // } // // TransformedEntriesSortedMap( // SortedMap fromMap, EntryTransformer transformer) { // super(fromMap, transformer); // } // // @Override // public Comparator comparator() { // return fromMap().comparator(); // } // // @Override // public K firstKey() { // return fromMap().firstKey(); // } // // @Override // public SortedMap headMap(K toKey) { // return transformEntries(fromMap().headMap(toKey), transformer); // } // // @Override // public K lastKey() { // return fromMap().lastKey(); // } // // @Override // public SortedMap subMap(K fromKey, K toKey) { // return transformEntries(fromMap().subMap(fromKey, toKey), transformer); // } // // @Override // public SortedMap tailMap(K fromKey) { // return transformEntries(fromMap().tailMap(fromKey), transformer); // } // } // // @GwtIncompatible // NavigableMap // private static class TransformedEntriesNavigableMap // extends TransformedEntriesSortedMap implements NavigableMap { // // TransformedEntriesNavigableMap( // NavigableMap fromMap, EntryTransformer transformer) { // super(fromMap, transformer); // } // // @Override // public Entry ceilingEntry(K key) { // return transformEntry(fromMap().ceilingEntry(key)); // } // // @Override // public K ceilingKey(K key) { // return fromMap().ceilingKey(key); // } // // @Override // public NavigableSet descendingKeySet() { // return fromMap().descendingKeySet(); // } // // @Override // public NavigableMap descendingMap() { // return transformEntries(fromMap().descendingMap(), transformer); // } // // @Override // public Entry firstEntry() { // return transformEntry(fromMap().firstEntry()); // } // // @Override // public Entry floorEntry(K key) { // return transformEntry(fromMap().floorEntry(key)); // } // // @Override // public K floorKey(K key) { // return fromMap().floorKey(key); // } // // @Override // public NavigableMap headMap(K toKey) { // return headMap(toKey, false); // } // // @Override // public NavigableMap headMap(K toKey, boolean inclusive) { // return transformEntries(fromMap().headMap(toKey, inclusive), transformer); // } // // @Override // public Entry higherEntry(K key) { // return transformEntry(fromMap().higherEntry(key)); // } // // @Override // public K higherKey(K key) { // return fromMap().higherKey(key); // } // // @Override // public Entry lastEntry() { // return transformEntry(fromMap().lastEntry()); // } // // @Override // public Entry lowerEntry(K key) { // return transformEntry(fromMap().lowerEntry(key)); // } // // @Override // public K lowerKey(K key) { // return fromMap().lowerKey(key); // } // // @Override // public NavigableSet navigableKeySet() { // return fromMap().navigableKeySet(); // } // // @Override // public Entry pollFirstEntry() { // return transformEntry(fromMap().pollFirstEntry()); // } // // @Override // public Entry pollLastEntry() { // return transformEntry(fromMap().pollLastEntry()); // } // // @Override // public NavigableMap subMap( // K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { // return transformEntries( // fromMap().subMap(fromKey, fromInclusive, toKey, toInclusive), transformer); // } // // @Override // public NavigableMap subMap(K fromKey, K toKey) { // return subMap(fromKey, true, toKey, false); // } // // @Override // public NavigableMap tailMap(K fromKey) { // return tailMap(fromKey, true); // } // // @Override // public NavigableMap tailMap(K fromKey, boolean inclusive) { // return transformEntries(fromMap().tailMap(fromKey, inclusive), transformer); // } // // private @Nullable Entry transformEntry(@Nullable Entry entry) { // return (entry == null) ? null : Maps.transformEntry(transformer, entry); // } // // @Override // protected NavigableMap fromMap() { // return (NavigableMap) super.fromMap(); // } // } // // static Predicate> keyPredicateOnEntries(Predicate keyPredicate) { // return compose(keyPredicate, Maps.keyFunction()); // } // // static Predicate> valuePredicateOnEntries(Predicate valuePredicate) { // return compose(valuePredicate, Maps.valueFunction()); // } // // /** // * Returns a 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. // * // *

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}. // * // *

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. // * // *

The returned map isn't threadsafe or serializable, even if {@code unfiltered} is. // * // *

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 // * not needed, it may be faster to copy the filtered map and use the copy. // * // *

Warning: {@code keyPredicate} must be consistent with equals, as documented at // * {@link Predicate#apply}. Do not provide a predicate such as {@code // * Predicates.instanceOf(ArrayList.class)}, which is inconsistent with equals. // */ // public static Map filterKeys( // Map unfiltered, final Predicate keyPredicate) { // checkNotNull(keyPredicate); // Predicate> entryPredicate = keyPredicateOnEntries(keyPredicate); // return (unfiltered instanceof AbstractFilteredMap) // ? filterFiltered((AbstractFilteredMap) unfiltered, entryPredicate) // : new FilteredKeyMap(checkNotNull(unfiltered), keyPredicate, entryPredicate); // } // // /** // * Returns a sorted 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. // * // *

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}. // * // *

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. // * // *

The returned map isn't threadsafe or serializable, even if {@code unfiltered} is. // * // *

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 // * not needed, it may be faster to copy the filtered map and use the copy. // * // *

Warning: {@code keyPredicate} must be consistent with equals, as documented at // * {@link Predicate#apply}. Do not provide a predicate such as {@code // * Predicates.instanceOf(ArrayList.class)}, which is inconsistent with equals. // * // * @since 11.0 // */ // public static SortedMap filterKeys( // SortedMap unfiltered, final Predicate keyPredicate) { // // TODO(lowasser): Return a subclass of Maps.FilteredKeyMap for slightly better // // performance. // return filterEntries(unfiltered, Maps.keyPredicateOnEntries(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. // * // *

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}. // * // *

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. // * // *

The returned map isn't threadsafe or serializable, even if {@code unfiltered} is. // * // *

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 // * not needed, it may be faster to copy the filtered map and use the copy. // * // *

Warning: {@code keyPredicate} must be consistent with equals, 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 NavigableMap filterKeys( // NavigableMap unfiltered, final Predicate keyPredicate) { // // TODO(lowasser): Return a subclass of Maps.FilteredKeyMap for slightly better // // performance. // return filterEntries(unfiltered, Maps.keyPredicateOnEntries(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. // * // *

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}. // * // *

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. // * // *

The returned bimap isn't threadsafe or serializable, even if {@code unfiltered} is. // * // *

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 not // * needed, it may be faster to copy the filtered bimap and use the copy. // * // *

Warning: {@code entryPredicate} must be consistent with equals , as documented // * at {@link Predicate#apply}. // * // * @since 14.0 // */ // public static BiMap filterKeys( // BiMap unfiltered, final Predicate keyPredicate) { // checkNotNull(keyPredicate); // return filterEntries(unfiltered, Maps.keyPredicateOnEntries(keyPredicate)); // } // // /** // * Returns a 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. // * // *

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}. // * // *

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. // * // *

The returned map isn't threadsafe or serializable, even if {@code unfiltered} is. // * // *

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 // * not needed, it may be faster to copy the filtered map and use the copy. // * // *

Warning: {@code valuePredicate} must be consistent with equals, as documented // * at {@link Predicate#apply}. Do not provide a predicate such as {@code // * Predicates.instanceOf(ArrayList.class)}, which is inconsistent with equals. // */ // public static Map filterValues( // Map unfiltered, final Predicate valuePredicate) { // return filterEntries(unfiltered, Maps.valuePredicateOnEntries(valuePredicate)); // } // // /** // * Returns a sorted 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. // * // *

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}. // * // *

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. // * // *

The returned map isn't threadsafe or serializable, even if {@code unfiltered} is. // * // *

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 // * not needed, it may be faster to copy the filtered map and use the copy. // * // *

Warning: {@code valuePredicate} must be consistent with equals, as documented // * at {@link Predicate#apply}. Do not provide a predicate such as {@code // * Predicates.instanceOf(ArrayList.class)}, which is inconsistent with equals. // * // * @since 11.0 // */ // public static SortedMap filterValues( // SortedMap unfiltered, final Predicate valuePredicate) { // return filterEntries(unfiltered, Maps.valuePredicateOnEntries(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. // * // *

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}. // * // *

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. // * // *

The returned map isn't threadsafe or serializable, even if {@code unfiltered} is. // * // *

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 // * not needed, it may be faster to copy the filtered map and use the copy. // * // *

Warning: {@code valuePredicate} must be consistent with equals, 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 NavigableMap filterValues( // NavigableMap unfiltered, final Predicate valuePredicate) { // return filterEntries(unfiltered, Maps.valuePredicateOnEntries(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. // * // *

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. // * // *

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. // * // *

The returned bimap isn't threadsafe or serializable, even if {@code unfiltered} is. // * // *

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 not // * needed, it may be faster to copy the filtered bimap and use the copy. // * // *

Warning: {@code entryPredicate} must be consistent with equals , as documented // * at {@link Predicate#apply}. // * // * @since 14.0 // */ // public static BiMap filterValues( // BiMap unfiltered, final Predicate valuePredicate) { // return filterEntries(unfiltered, Maps.valuePredicateOnEntries(valuePredicate)); // } // // /** // * Returns a 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. // * // *

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. // * // *

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. // * // *

The returned map isn't threadsafe or serializable, even if {@code unfiltered} is. // * // *

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 // * not needed, it may be faster to copy the filtered map and use the copy. // * // *

Warning: {@code entryPredicate} must be consistent with equals, as documented // * at {@link Predicate#apply}. // */ // public static Map filterEntries( // Map unfiltered, Predicate> entryPredicate) { // checkNotNull(entryPredicate); // return (unfiltered instanceof AbstractFilteredMap) // ? filterFiltered((AbstractFilteredMap) unfiltered, entryPredicate) // : new FilteredEntryMap(checkNotNull(unfiltered), entryPredicate); // } // // /** // * 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. // * // *

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. // * // *

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. // * // *

The returned map isn't threadsafe or serializable, even if {@code unfiltered} is. // * // *

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 // * not needed, it may be faster to copy the filtered map and use the copy. // * // *

Warning: {@code entryPredicate} must be consistent with equals, as documented // * at {@link Predicate#apply}. // * // * @since 11.0 // */ // public static SortedMap filterEntries( // SortedMap unfiltered, Predicate> entryPredicate) { // checkNotNull(entryPredicate); // return (unfiltered instanceof FilteredEntrySortedMap) // ? filterFiltered((FilteredEntrySortedMap) unfiltered, entryPredicate) // : new FilteredEntrySortedMap(checkNotNull(unfiltered), entryPredicate); // } // // /** // * 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. // * // *

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. // * // *

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. // * // *

The returned map isn't threadsafe or serializable, even if {@code unfiltered} is. // * // *

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 // * not needed, it may be faster to copy the filtered map and use the copy. // * // *

Warning: {@code entryPredicate} must be consistent with equals, as documented // * at {@link Predicate#apply}. // * // * @since 14.0 // */ // @GwtIncompatible // NavigableMap // public static NavigableMap filterEntries( // NavigableMap unfiltered, Predicate> entryPredicate) { // checkNotNull(entryPredicate); // return (unfiltered instanceof FilteredEntryNavigableMap) // ? filterFiltered((FilteredEntryNavigableMap) unfiltered, entryPredicate) // : new FilteredEntryNavigableMap(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. // * // *

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. // * // *

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. // * // *

The returned bimap isn't threadsafe or serializable, even if {@code unfiltered} is. // * // *

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 // * not needed, it may be faster to copy the filtered bimap and use the copy. // * // *

Warning: {@code entryPredicate} must be consistent with equals , as documented // * at {@link Predicate#apply}. // * // * @since 14.0 // */ // public static BiMap filterEntries( // BiMap unfiltered, Predicate> entryPredicate) { // checkNotNull(unfiltered); // checkNotNull(entryPredicate); // return (unfiltered instanceof FilteredEntryBiMap) // ? filterFiltered((FilteredEntryBiMap) unfiltered, entryPredicate) // : new FilteredEntryBiMap(unfiltered, entryPredicate); // } // // /** // * Support {@code clear()}, {@code removeAll()}, and {@code retainAll()} when filtering a filtered // * map. // */ // private static Map filterFiltered( // AbstractFilteredMap map, Predicate> entryPredicate) { // return new FilteredEntryMap<>( // map.unfiltered, Predicates.>and(map.predicate, entryPredicate)); // } // // /** // * Support {@code clear()}, {@code removeAll()}, and {@code retainAll()} when filtering a filtered // * sorted map. // */ // private static SortedMap filterFiltered( // FilteredEntrySortedMap map, Predicate> entryPredicate) { // Predicate> predicate = Predicates.>and(map.predicate, entryPredicate); // return new FilteredEntrySortedMap<>(map.sortedMap(), predicate); // } // // /** // * Support {@code clear()}, {@code removeAll()}, and {@code retainAll()} when filtering a filtered // * navigable map. // */ // @GwtIncompatible // NavigableMap // private static NavigableMap filterFiltered( // FilteredEntryNavigableMap map, Predicate> entryPredicate) { // Predicate> predicate = // Predicates.>and(map.entryPredicate, entryPredicate); // return new FilteredEntryNavigableMap<>(map.unfiltered, predicate); // } // // /** // * Support {@code clear()}, {@code removeAll()}, and {@code retainAll()} when filtering a filtered // * map. // */ // private static BiMap filterFiltered( // FilteredEntryBiMap map, Predicate> entryPredicate) { // Predicate> predicate = Predicates.>and(map.predicate, entryPredicate); // return new FilteredEntryBiMap<>(map.unfiltered(), predicate); // } // // private abstract static class AbstractFilteredMap extends ViewCachingAbstractMap { // final Map unfiltered; // final Predicate> predicate; // // AbstractFilteredMap(Map unfiltered, Predicate> predicate) { // this.unfiltered = unfiltered; // this.predicate = predicate; // } // // boolean apply(@Nullable Object key, @Nullable V value) { // // This method is called only when the key is in the map, implying that // // key is a K. // @SuppressWarnings("unchecked") // K k = (K) key; // return predicate.apply(Maps.immutableEntry(k, value)); // } // // @Override // public V put(K key, V value) { // checkArgument(apply(key, value)); // return unfiltered.put(key, value); // } // // @Override // public void putAll(Map map) { // for (Entry entry : map.entrySet()) { // checkArgument(apply(entry.getKey(), entry.getValue())); // } // unfiltered.putAll(map); // } // // @Override // public boolean containsKey(Object key) { // return unfiltered.containsKey(key) && apply(key, unfiltered.get(key)); // } // // @Override // public V get(Object key) { // V value = unfiltered.get(key); // return ((value != null) && apply(key, value)) ? value : null; // } // // @Override // public boolean isEmpty() { // return entrySet().isEmpty(); // } // // @Override // public V remove(Object key) { // return containsKey(key) ? unfiltered.remove(key) : null; // } // // @Override // Collection createValues() { // return new FilteredMapValues<>(this, unfiltered, predicate); // } // } // // private static final class FilteredMapValues extends Maps.Values { // final Map unfiltered; // final Predicate> predicate; // // FilteredMapValues( // Map filteredMap, Map unfiltered, Predicate> predicate) { // super(filteredMap); // this.unfiltered = unfiltered; // this.predicate = predicate; // } // // @Override // public boolean remove(Object o) { // Iterator> entryItr = unfiltered.entrySet().iterator(); // while (entryItr.hasNext()) { // Entry entry = entryItr.next(); // if (predicate.apply(entry) && Objects.equal(entry.getValue(), o)) { // entryItr.remove(); // return true; // } // } // return false; // } // // @Override // public boolean removeAll(Collection collection) { // Iterator> entryItr = unfiltered.entrySet().iterator(); // boolean result = false; // while (entryItr.hasNext()) { // Entry entry = entryItr.next(); // if (predicate.apply(entry) && collection.contains(entry.getValue())) { // entryItr.remove(); // result = true; // } // } // return result; // } // // @Override // public boolean retainAll(Collection collection) { // Iterator> entryItr = unfiltered.entrySet().iterator(); // boolean result = false; // while (entryItr.hasNext()) { // Entry entry = entryItr.next(); // if (predicate.apply(entry) && !collection.contains(entry.getValue())) { // entryItr.remove(); // result = true; // } // } // return result; // } // // @Override // public Object[] toArray() { // // creating an ArrayList so filtering happens once // return Lists.newArrayList(iterator()).toArray(); // } // // @Override // public T[] toArray(T[] array) { // return Lists.newArrayList(iterator()).toArray(array); // } // } // // private static class FilteredKeyMap extends AbstractFilteredMap { // final Predicate keyPredicate; // // FilteredKeyMap( // Map unfiltered, // Predicate keyPredicate, // Predicate> entryPredicate) { // super(unfiltered, entryPredicate); // this.keyPredicate = keyPredicate; // } // // @Override // protected Set> createEntrySet() { // return Sets.filter(unfiltered.entrySet(), predicate); // } // // @Override // Set createKeySet() { // return Sets.filter(unfiltered.keySet(), keyPredicate); // } // // // The cast is called only when the key is in the unfiltered map, implying // // that key is a K. // @Override // @SuppressWarnings("unchecked") // public boolean containsKey(Object key) { // return unfiltered.containsKey(key) && keyPredicate.apply((K) key); // } // } // // static class FilteredEntryMap extends AbstractFilteredMap { // /** // * Entries in this set satisfy the predicate, but they don't validate the input to {@code // * Entry.setValue()}. // */ // final Set> filteredEntrySet; // // FilteredEntryMap(Map unfiltered, Predicate> entryPredicate) { // super(unfiltered, entryPredicate); // filteredEntrySet = Sets.filter(unfiltered.entrySet(), predicate); // } // // @Override // protected Set> createEntrySet() { // return new EntrySet(); // } // // @WeakOuter // private class EntrySet extends ForwardingSet> { // @Override // protected Set> delegate() { // return filteredEntrySet; // } // // @Override // public Iterator> iterator() { // return new TransformedIterator, Entry>(filteredEntrySet.iterator()) { // @Override // Entry transform(final Entry entry) { // return new ForwardingMapEntry() { // @Override // protected Entry delegate() { // return entry; // } // // @Override // public V setValue(V newValue) { // checkArgument(apply(getKey(), newValue)); // return super.setValue(newValue); // } // }; // } // }; // } // } // // @Override // Set createKeySet() { // return new KeySet(); // } // // static boolean removeAllKeys( // Map map, Predicate> entryPredicate, Collection keyCollection) { // Iterator> entryItr = map.entrySet().iterator(); // boolean result = false; // while (entryItr.hasNext()) { // Entry entry = entryItr.next(); // if (entryPredicate.apply(entry) && keyCollection.contains(entry.getKey())) { // entryItr.remove(); // result = true; // } // } // return result; // } // // static boolean retainAllKeys( // Map map, Predicate> entryPredicate, Collection keyCollection) { // Iterator> entryItr = map.entrySet().iterator(); // boolean result = false; // while (entryItr.hasNext()) { // Entry entry = entryItr.next(); // if (entryPredicate.apply(entry) && !keyCollection.contains(entry.getKey())) { // entryItr.remove(); // result = true; // } // } // return result; // } // // @WeakOuter // class KeySet extends Maps.KeySet { // KeySet() { // super(FilteredEntryMap.this); // } // // @Override // public boolean remove(Object o) { // if (containsKey(o)) { // unfiltered.remove(o); // return true; // } // return false; // } // // @Override // public boolean removeAll(Collection collection) { // return removeAllKeys(unfiltered, predicate, collection); // } // // @Override // public boolean retainAll(Collection collection) { // return retainAllKeys(unfiltered, predicate, collection); // } // // @Override // public Object[] toArray() { // // creating an ArrayList so filtering happens once // return Lists.newArrayList(iterator()).toArray(); // } // // @Override // public T[] toArray(T[] array) { // return Lists.newArrayList(iterator()).toArray(array); // } // } // } // // private static class FilteredEntrySortedMap extends FilteredEntryMap // implements SortedMap { // // FilteredEntrySortedMap( // SortedMap unfiltered, Predicate> entryPredicate) { // super(unfiltered, entryPredicate); // } // // SortedMap sortedMap() { // return (SortedMap) unfiltered; // } // // @Override // public SortedSet keySet() { // return (SortedSet) super.keySet(); // } // // @Override // SortedSet createKeySet() { // return new SortedKeySet(); // } // // @WeakOuter // class SortedKeySet extends KeySet implements SortedSet { // @Override // public Comparator comparator() { // return sortedMap().comparator(); // } // // @Override // public SortedSet subSet(K fromElement, K toElement) { // return (SortedSet) subMap(fromElement, toElement).keySet(); // } // // @Override // public SortedSet headSet(K toElement) { // return (SortedSet) headMap(toElement).keySet(); // } // // @Override // public SortedSet tailSet(K fromElement) { // return (SortedSet) tailMap(fromElement).keySet(); // } // // @Override // public K first() { // return firstKey(); // } // // @Override // public K last() { // return lastKey(); // } // } // // @Override // public Comparator comparator() { // return sortedMap().comparator(); // } // // @Override // public K firstKey() { // // correctly throws NoSuchElementException when filtered map is empty. // return keySet().iterator().next(); // } // // @Override // public K lastKey() { // SortedMap headMap = sortedMap(); // while (true) { // // correctly throws NoSuchElementException when filtered map is empty. // K key = headMap.lastKey(); // if (apply(key, unfiltered.get(key))) { // return key; // } // headMap = sortedMap().headMap(key); // } // } // // @Override // public SortedMap headMap(K toKey) { // return new FilteredEntrySortedMap<>(sortedMap().headMap(toKey), predicate); // } // // @Override // public SortedMap subMap(K fromKey, K toKey) { // return new FilteredEntrySortedMap<>(sortedMap().subMap(fromKey, toKey), predicate); // } // // @Override // public SortedMap tailMap(K fromKey) { // return new FilteredEntrySortedMap<>(sortedMap().tailMap(fromKey), predicate); // } // } // // @GwtIncompatible // NavigableMap // private static class FilteredEntryNavigableMap extends AbstractNavigableMap { // /* // * It's less code to extend AbstractNavigableMap and forward the filtering logic to // * FilteredEntryMap than to extend FilteredEntrySortedMap and reimplement all the NavigableMap // * methods. // */ // // private final NavigableMap unfiltered; // private final Predicate> entryPredicate; // private final Map filteredDelegate; // // FilteredEntryNavigableMap( // NavigableMap unfiltered, Predicate> entryPredicate) { // this.unfiltered = checkNotNull(unfiltered); // this.entryPredicate = entryPredicate; // this.filteredDelegate = new FilteredEntryMap<>(unfiltered, entryPredicate); // } // // @Override // public Comparator comparator() { // return unfiltered.comparator(); // } // // @Override // public NavigableSet navigableKeySet() { // return new Maps.NavigableKeySet(this) { // @Override // public boolean removeAll(Collection collection) { // return FilteredEntryMap.removeAllKeys(unfiltered, entryPredicate, collection); // } // // @Override // public boolean retainAll(Collection collection) { // return FilteredEntryMap.retainAllKeys(unfiltered, entryPredicate, collection); // } // }; // } // // @Override // public Collection values() { // return new FilteredMapValues<>(this, unfiltered, entryPredicate); // } // // @Override // Iterator> entryIterator() { // return Iterators.filter(unfiltered.entrySet().iterator(), entryPredicate); // } // // @Override // Iterator> descendingEntryIterator() { // return Iterators.filter(unfiltered.descendingMap().entrySet().iterator(), entryPredicate); // } // // @Override // public int size() { // return filteredDelegate.size(); // } // // @Override // public boolean isEmpty() { // return !Iterables.any(unfiltered.entrySet(), entryPredicate); // } // // @Override // public @Nullable V get(@Nullable Object key) { // return filteredDelegate.get(key); // } // // @Override // public boolean containsKey(@Nullable Object key) { // return filteredDelegate.containsKey(key); // } // // @Override // public V put(K key, V value) { // return filteredDelegate.put(key, value); // } // // @Override // public V remove(@Nullable Object key) { // return filteredDelegate.remove(key); // } // // @Override // public void putAll(Map m) { // filteredDelegate.putAll(m); // } // // @Override // public void clear() { // filteredDelegate.clear(); // } // // @Override // public Set> entrySet() { // return filteredDelegate.entrySet(); // } // // @Override // public Entry pollFirstEntry() { // return Iterables.removeFirstMatching(unfiltered.entrySet(), entryPredicate); // } // // @Override // public Entry pollLastEntry() { // return Iterables.removeFirstMatching(unfiltered.descendingMap().entrySet(), entryPredicate); // } // // @Override // public NavigableMap descendingMap() { // return filterEntries(unfiltered.descendingMap(), entryPredicate); // } // // @Override // public NavigableMap subMap( // K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { // return filterEntries( // unfiltered.subMap(fromKey, fromInclusive, toKey, toInclusive), entryPredicate); // } // // @Override // public NavigableMap headMap(K toKey, boolean inclusive) { // return filterEntries(unfiltered.headMap(toKey, inclusive), entryPredicate); // } // // @Override // public NavigableMap tailMap(K fromKey, boolean inclusive) { // return filterEntries(unfiltered.tailMap(fromKey, inclusive), entryPredicate); // } // } // // static final class FilteredEntryBiMap extends FilteredEntryMap // implements BiMap { // @RetainedWith private final BiMap inverse; // // private static Predicate> inversePredicate( // final Predicate> forwardPredicate) { // return new Predicate>() { // @Override // public boolean apply(Entry input) { // return forwardPredicate.apply(Maps.immutableEntry(input.getValue(), input.getKey())); // } // }; // } // // FilteredEntryBiMap(BiMap delegate, Predicate> predicate) { // super(delegate, predicate); // this.inverse = // new FilteredEntryBiMap<>(delegate.inverse(), inversePredicate(predicate), this); // } // // private FilteredEntryBiMap( // BiMap delegate, Predicate> predicate, BiMap inverse) { // super(delegate, predicate); // this.inverse = inverse; // } // // BiMap unfiltered() { // return (BiMap) unfiltered; // } // // @Override // public V forcePut(@Nullable K key, @Nullable V value) { // checkArgument(apply(key, value)); // return unfiltered().forcePut(key, value); // } // // @Override // public void replaceAll(BiFunction function) { // unfiltered() // .replaceAll( // (key, value) -> // predicate.apply(Maps.immutableEntry(key, value)) // ? function.apply(key, value) // : value); // } // // @Override // public BiMap inverse() { // return inverse; // } // // @Override // public Set values() { // return inverse.keySet(); // } // } // // /** // * 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}. // * // *

The returned navigable map will be serializable if the specified navigable map is // * serializable. // * // *

This method's signature will not permit you to convert a {@code NavigableMap} to a {@code NavigableMap}. If it permitted this, the returned map's {@code // * comparator()} method might return a {@code Comparator}, which works only on a // * particular subtype of {@code K}, but promise that it's a {@code Comparator}, which // * must work on any type of {@code K}. // * // * @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 NavigableMap unmodifiableNavigableMap( // NavigableMap map) { // checkNotNull(map); // if (map instanceof UnmodifiableNavigableMap) { // @SuppressWarnings("unchecked") // covariant // NavigableMap result = (NavigableMap) map; // return result; // } else { // return new UnmodifiableNavigableMap<>(map); // } // } // // private static @Nullable Entry unmodifiableOrNull( // @Nullable Entry entry) { // return (entry == null) ? null : Maps.unmodifiableEntry(entry); // } // // @GwtIncompatible // NavigableMap // static class UnmodifiableNavigableMap extends ForwardingSortedMap // implements NavigableMap, Serializable { // private final NavigableMap delegate; // // UnmodifiableNavigableMap(NavigableMap delegate) { // this.delegate = delegate; // } // // UnmodifiableNavigableMap( // NavigableMap delegate, UnmodifiableNavigableMap descendingMap) { // this.delegate = delegate; // this.descendingMap = descendingMap; // } // // @Override // protected SortedMap delegate() { // return Collections.unmodifiableSortedMap(delegate); // } // // @Override // public Entry lowerEntry(K key) { // return unmodifiableOrNull(delegate.lowerEntry(key)); // } // // @Override // public K lowerKey(K key) { // return delegate.lowerKey(key); // } // // @Override // public Entry floorEntry(K key) { // return unmodifiableOrNull(delegate.floorEntry(key)); // } // // @Override // public K floorKey(K key) { // return delegate.floorKey(key); // } // // @Override // public Entry ceilingEntry(K key) { // return unmodifiableOrNull(delegate.ceilingEntry(key)); // } // // @Override // public K ceilingKey(K key) { // return delegate.ceilingKey(key); // } // // @Override // public Entry higherEntry(K key) { // return unmodifiableOrNull(delegate.higherEntry(key)); // } // // @Override // public K higherKey(K key) { // return delegate.higherKey(key); // } // // @Override // public Entry firstEntry() { // return unmodifiableOrNull(delegate.firstEntry()); // } // // @Override // public Entry lastEntry() { // return unmodifiableOrNull(delegate.lastEntry()); // } // // @Override // public final Entry pollFirstEntry() { // throw new UnsupportedOperationException(); // } // // @Override // public final Entry pollLastEntry() { // throw new UnsupportedOperationException(); // } // // private transient @MonotonicNonNull UnmodifiableNavigableMap descendingMap; // // @Override // public NavigableMap descendingMap() { // UnmodifiableNavigableMap result = descendingMap; // return (result == null) // ? descendingMap = new UnmodifiableNavigableMap<>(delegate.descendingMap(), this) // : result; // } // // @Override // public Set keySet() { // return navigableKeySet(); // } // // @Override // public NavigableSet navigableKeySet() { // return Sets.unmodifiableNavigableSet(delegate.navigableKeySet()); // } // // @Override // public NavigableSet descendingKeySet() { // return Sets.unmodifiableNavigableSet(delegate.descendingKeySet()); // } // // @Override // public SortedMap subMap(K fromKey, K toKey) { // return subMap(fromKey, true, toKey, false); // } // // @Override // public NavigableMap subMap( // K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { // return Maps.unmodifiableNavigableMap( // delegate.subMap(fromKey, fromInclusive, toKey, toInclusive)); // } // // @Override // public SortedMap headMap(K toKey) { // return headMap(toKey, false); // } // // @Override // public NavigableMap headMap(K toKey, boolean inclusive) { // return Maps.unmodifiableNavigableMap(delegate.headMap(toKey, inclusive)); // } // // @Override // public SortedMap tailMap(K fromKey) { // return tailMap(fromKey, true); // } // // @Override // public NavigableMap 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 all access to the backing // * navigable map is accomplished through the returned navigable map (or its views). // * // *

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. // * // *

{@code
//   * NavigableMap map = synchronizedNavigableMap(new TreeMap());
//   *
//   * // Needn't be in synchronized block
//   * NavigableSet set = map.navigableKeySet();
//   *
//   * synchronized (map) { // Synchronizing on map, not set!
//   *   Iterator it = set.iterator(); // Must be in synchronized block
//   *   while (it.hasNext()) {
//   *     foo(it.next());
//   *   }
//   * }
//   * }
// * // *

or: // * // *

{@code
//   * NavigableMap map = synchronizedNavigableMap(new TreeMap());
//   * NavigableMap map2 = map.subMap(foo, false, bar, true);
//   *
//   * // Needn't be in synchronized block
//   * NavigableSet set2 = map2.descendingKeySet();
//   *
//   * synchronized (map) { // Synchronizing on map, not map2 or set2!
//   *   Iterator it = set2.iterator(); // Must be in synchronized block
//   *   while (it.hasNext()) {
//   *     foo(it.next());
//   *   }
//   * }
//   * }
// * // *

Failure to follow this advice may result in non-deterministic behavior. // * // *

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 NavigableMap synchronizedNavigableMap( // NavigableMap navigableMap) { // return Synchronized.navigableMap(navigableMap); // } // // /** // * {@code AbstractMap} extension that makes it easy to cache customized keySet, values, and // * entrySet views. // */ // @GwtCompatible // abstract static class ViewCachingAbstractMap extends AbstractMap { // /** // * 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} is first called. // */ // abstract Set> createEntrySet(); // // private transient @MonotonicNonNull Set> entrySet; // // @Override // public Set> entrySet() { // Set> result = entrySet; // return (result == null) ? entrySet = createEntrySet() : result; // } // // private transient @MonotonicNonNull Set keySet; // // @Override // public Set keySet() { // Set result = keySet; // return (result == null) ? keySet = createKeySet() : result; // } // // Set createKeySet() { // return new KeySet<>(this); // } // // private transient @MonotonicNonNull Collection values; // // @Override // public Collection values() { // Collection result = values; // return (result == null) ? values = createValues() : result; // } // // Collection createValues() { // return new Values<>(this); // } // } abstract static class IteratorBasedAbstractMap extends AbstractMap { @Override public abstract int size(); abstract Iterator> entryIterator(); Spliterator> entrySpliterator() { return Spliterators.spliterator( entryIterator(), size(), Spliterator.SIZED | Spliterator.DISTINCT); } @Override public Set> entrySet() { return new EntrySet() { @Override Map map() { return IteratorBasedAbstractMap.this; } @Override public Iterator> iterator() { return entryIterator(); } @Override public Spliterator> spliterator() { return entrySpliterator(); } @Override public void forEach(Consumer> action) { forEachEntry(action); } }; } void forEachEntry(Consumer> action) { entryIterator().forEachRemaining(action); } @Override public void clear() { Iterators.clear(entryIterator()); } } /** * Delegates to {@link Map#get}. Returns {@code null} on {@code ClassCastException} and {@code * NullPointerException}. */ static V safeGet(Map map, @Nullable Object key) { checkNotNull(map); try { return map.get(key); } catch (ClassCastException | NullPointerException e) { return null; } } /** * Delegates to {@link Map#containsKey}. Returns {@code false} on {@code ClassCastException} and * {@code NullPointerException}. */ static boolean safeContainsKey(Map map, Object key) { checkNotNull(map); try { return map.containsKey(key); } catch (ClassCastException | NullPointerException e) { return false; } } /** * Delegates to {@link Map#remove}. Returns {@code null} on {@code ClassCastException} and {@code * NullPointerException}. */ static V safeRemove(Map map, Object key) { checkNotNull(map); try { return map.remove(key); } catch (ClassCastException | NullPointerException e) { return null; } } // /** An admittedly inefficient implementation of {@link Map#containsKey}. */ // static boolean containsKeyImpl(Map map, @Nullable Object key) { // return Iterators.contains(keyIterator(map.entrySet().iterator()), key); // } // // /** An implementation of {@link Map#containsValue}. */ // static boolean containsValueImpl(Map map, @Nullable Object value) { // return Iterators.contains(valueIterator(map.entrySet().iterator()), value); // } // // /** // * Implements {@code Collection.contains} safely for forwarding collections of map entries. If // * {@code o} is an instance of {@code Entry}, it is wrapped using {@link #unmodifiableEntry} to // * protect against a possible nefarious equals method. // * // *

Note that {@code c} is the backing (delegate) collection, rather than the forwarding // * collection. // * // * @param c the delegate (unwrapped) collection of map entries // * @param o the object that might be contained in {@code c} // * @return {@code true} if {@code c} contains {@code o} // */ // static boolean containsEntryImpl(Collection> c, Object o) { // if (!(o instanceof Entry)) { // return false; // } // return c.contains(unmodifiableEntry((Entry) o)); // } // // /** // * Implements {@code Collection.remove} safely for forwarding collections of map entries. If // * {@code o} is an instance of {@code Entry}, it is wrapped using {@link #unmodifiableEntry} to // * protect against a possible nefarious equals method. // * // *

Note that {@code c} is backing (delegate) collection, rather than the forwarding collection. // * // * @param c the delegate (unwrapped) collection of map entries // * @param o the object to remove from {@code c} // * @return {@code true} if {@code c} was changed // */ // static boolean removeEntryImpl(Collection> c, Object o) { // if (!(o instanceof Entry)) { // return false; // } // return c.remove(unmodifiableEntry((Entry) o)); // } /** An implementation of {@link Map#equals}. */ static boolean equalsImpl(Map map, Object object) { if (map == object) { return true; } else if (object instanceof Map) { Map o = (Map) object; return map.entrySet().equals(o.entrySet()); } return false; } // /** An implementation of {@link Map#toString}. */ // static String toStringImpl(Map map) { // StringBuilder sb = Collections2.newStringBuilderForCollection(map.size()).append('{'); // boolean first = true; // for (Entry entry : map.entrySet()) { // if (!first) { // sb.append(", "); // } // first = false; // sb.append(entry.getKey()).append('=').append(entry.getValue()); // } // return sb.append('}').toString(); // } /** An implementation of {@link Map#putAll}. */ static void putAllImpl(Map self, Map map) { for (Entry entry : map.entrySet()) { self.put(entry.getKey(), entry.getValue()); } } static class KeySet extends Sets.ImprovedAbstractSet { // @Weak final Map map; KeySet(Map map) { this.map = checkNotNull(map); } Map map() { return map; } @Override public Iterator iterator() { return keyIterator(map().entrySet().iterator()); } @Override public void forEach(Consumer action) { checkNotNull(action); // avoids entry allocation for those maps that allocate entries on iteration map.forEach((k, v) -> action.accept(k)); } @Override public int size() { return map().size(); } @Override public boolean isEmpty() { return map().isEmpty(); } @Override public boolean contains(Object o) { return map().containsKey(o); } @Override public boolean remove(Object o) { if (contains(o)) { map().remove(o); return true; } return false; } @Override public void clear() { map().clear(); } } static @Nullable K keyOrNull(@Nullable Entry entry) { return (entry == null) ? null : entry.getKey(); } static @Nullable V valueOrNull(@Nullable Entry entry) { return (entry == null) ? null : entry.getValue(); } // static class SortedKeySet extends KeySet implements SortedSet { // SortedKeySet(SortedMap map) { // super(map); // } // // @Override // SortedMap map() { // return (SortedMap) super.map(); // } // // @Override // public Comparator comparator() { // return map().comparator(); // } // // @Override // public SortedSet subSet(K fromElement, K toElement) { // return new SortedKeySet<>(map().subMap(fromElement, toElement)); // } // // @Override // public SortedSet headSet(K toElement) { // return new SortedKeySet<>(map().headMap(toElement)); // } // // @Override // public SortedSet tailSet(K fromElement) { // return new SortedKeySet<>(map().tailMap(fromElement)); // } // // @Override // public K first() { // return map().firstKey(); // } // // @Override // public K last() { // return map().lastKey(); // } // } // // @GwtIncompatible // NavigableMap // static class NavigableKeySet extends SortedKeySet implements NavigableSet { // NavigableKeySet(NavigableMap map) { // super(map); // } // // @Override // NavigableMap map() { // return (NavigableMap) map; // } // // @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 descendingSet() { // return map().descendingKeySet(); // } // // @Override // public Iterator descendingIterator() { // return descendingSet().iterator(); // } // // @Override // public NavigableSet subSet( // K fromElement, boolean fromInclusive, K toElement, boolean toInclusive) { // return map().subMap(fromElement, fromInclusive, toElement, toInclusive).navigableKeySet(); // } // // @Override // public SortedSet subSet(K fromElement, K toElement) { // return subSet(fromElement, true, toElement, false); // } // // @Override // public NavigableSet headSet(K toElement, boolean inclusive) { // return map().headMap(toElement, inclusive).navigableKeySet(); // } // // @Override // public SortedSet headSet(K toElement) { // return headSet(toElement, false); // } // // @Override // public NavigableSet tailSet(K fromElement, boolean inclusive) { // return map().tailMap(fromElement, inclusive).navigableKeySet(); // } // // @Override // public SortedSet tailSet(K fromElement) { // return tailSet(fromElement, true); // } // } // // static class Values extends AbstractCollection { // @Weak final Map map; // // Values(Map map) { // this.map = checkNotNull(map); // } // // final Map map() { // return map; // } // // @Override // public Iterator iterator() { // return valueIterator(map().entrySet().iterator()); // } // // @Override // public void forEach(Consumer action) { // checkNotNull(action); // // avoids allocation of entries for those maps that generate fresh entries on iteration // map.forEach((k, v) -> action.accept(v)); // } // // @Override // public boolean remove(Object o) { // try { // return super.remove(o); // } catch (UnsupportedOperationException e) { // for (Entry entry : map().entrySet()) { // if (Objects.equal(o, entry.getValue())) { // map().remove(entry.getKey()); // return true; // } // } // return false; // } // } // // @Override // public boolean removeAll(Collection c) { // try { // return super.removeAll(checkNotNull(c)); // } catch (UnsupportedOperationException e) { // Set toRemove = Sets.newHashSet(); // for (Entry entry : map().entrySet()) { // if (c.contains(entry.getValue())) { // toRemove.add(entry.getKey()); // } // } // return map().keySet().removeAll(toRemove); // } // } // // @Override // public boolean retainAll(Collection c) { // try { // return super.retainAll(checkNotNull(c)); // } catch (UnsupportedOperationException e) { // Set toRetain = Sets.newHashSet(); // for (Entry entry : map().entrySet()) { // if (c.contains(entry.getValue())) { // toRetain.add(entry.getKey()); // } // } // return map().keySet().retainAll(toRetain); // } // } // // @Override // public int size() { // return map().size(); // } // // @Override // public boolean isEmpty() { // return map().isEmpty(); // } // // @Override // public boolean contains(@Nullable Object o) { // return map().containsValue(o); // } // // @Override // public void clear() { // map().clear(); // } // } abstract static class EntrySet extends Sets.ImprovedAbstractSet> { abstract Map map(); @Override public int size() { return map().size(); } @Override public void clear() { map().clear(); } @Override public boolean contains(Object o) { if (o instanceof Entry) { Entry entry = (Entry) o; Object key = entry.getKey(); V value = Maps.safeGet(map(), key); return Objects.equal(value, entry.getValue()) && (value != null || map().containsKey(key)); } return false; } @Override public boolean isEmpty() { return map().isEmpty(); } @Override public boolean remove(Object o) { if (contains(o)) { Entry entry = (Entry) o; return map().keySet().remove(entry.getKey()); } return false; } @Override public boolean removeAll(Collection c) { try { return super.removeAll(checkNotNull(c)); } catch (UnsupportedOperationException e) { // if the iterators don't support remove return Sets.removeAllImpl(this, c.iterator()); } } @Override public boolean retainAll(Collection c) { try { return super.retainAll(checkNotNull(c)); } catch (UnsupportedOperationException e) { // if the iterators don't support remove Set keys = Sets.newHashSetWithExpectedSize(c.size()); for (Object o : c) { if (contains(o)) { Entry entry = (Entry) o; keys.add(entry.getKey()); } } return map().keySet().retainAll(keys); } } } // @GwtIncompatible // NavigableMap // abstract static class DescendingMap extends ForwardingMap // implements NavigableMap { // // abstract NavigableMap forward(); // // @Override // protected final Map delegate() { // return forward(); // } // // private transient @MonotonicNonNull Comparator comparator; // // @SuppressWarnings("unchecked") // @Override // public Comparator comparator() { // Comparator result = comparator; // if (result == null) { // Comparator 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 Ordering reverse(Comparator forward) { // return Ordering.from(forward).reverse(); // } // // @Override // public K firstKey() { // return forward().lastKey(); // } // // @Override // public K lastKey() { // return forward().firstKey(); // } // // @Override // public Entry lowerEntry(K key) { // return forward().higherEntry(key); // } // // @Override // public K lowerKey(K key) { // return forward().higherKey(key); // } // // @Override // public Entry floorEntry(K key) { // return forward().ceilingEntry(key); // } // // @Override // public K floorKey(K key) { // return forward().ceilingKey(key); // } // // @Override // public Entry ceilingEntry(K key) { // return forward().floorEntry(key); // } // // @Override // public K ceilingKey(K key) { // return forward().floorKey(key); // } // // @Override // public Entry higherEntry(K key) { // return forward().lowerEntry(key); // } // // @Override // public K higherKey(K key) { // return forward().lowerKey(key); // } // // @Override // public Entry firstEntry() { // return forward().lastEntry(); // } // // @Override // public Entry lastEntry() { // return forward().firstEntry(); // } // // @Override // public Entry pollFirstEntry() { // return forward().pollLastEntry(); // } // // @Override // public Entry pollLastEntry() { // return forward().pollFirstEntry(); // } // // @Override // public NavigableMap descendingMap() { // return forward(); // } // // private transient @MonotonicNonNull Set> entrySet; // // @Override // public Set> entrySet() { // Set> result = entrySet; // return (result == null) ? entrySet = createEntrySet() : result; // } // // abstract Iterator> entryIterator(); // // Set> createEntrySet() { // @WeakOuter // class EntrySetImpl extends EntrySet { // @Override // Map map() { // return DescendingMap.this; // } // // @Override // public Iterator> iterator() { // return entryIterator(); // } // } // return new EntrySetImpl(); // } // // @Override // public Set keySet() { // return navigableKeySet(); // } // // private transient @MonotonicNonNull NavigableSet navigableKeySet; // // @Override // public NavigableSet navigableKeySet() { // NavigableSet result = navigableKeySet; // return (result == null) ? navigableKeySet = new NavigableKeySet<>(this) : result; // } // // @Override // public NavigableSet descendingKeySet() { // return forward().navigableKeySet(); // } // // @Override // public NavigableMap subMap( // K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { // return forward().subMap(toKey, toInclusive, fromKey, fromInclusive).descendingMap(); // } // // @Override // public SortedMap subMap(K fromKey, K toKey) { // return subMap(fromKey, true, toKey, false); // } // // @Override // public NavigableMap headMap(K toKey, boolean inclusive) { // return forward().tailMap(toKey, inclusive).descendingMap(); // } // // @Override // public SortedMap headMap(K toKey) { // return headMap(toKey, false); // } // // @Override // public NavigableMap tailMap(K fromKey, boolean inclusive) { // return forward().headMap(fromKey, inclusive).descendingMap(); // } // // @Override // public SortedMap tailMap(K fromKey) { // return tailMap(fromKey, true); // } // // @Override // public Collection values() { // return new Values<>(this); // } // // @Override // public String toString() { // return standardToString(); // } // } // // /** Returns a map from the ith element of list to i. */ // static ImmutableMap indexMap(Collection list) { // ImmutableMap.Builder builder = new ImmutableMap.Builder<>(list.size()); // int i = 0; // for (E e : list) { // builder.put(e, i++); // } // return builder.build(); // } // // /** // * Returns a view of the portion of {@code map} whose keys are contained by {@code range}. // * // *

This method delegates to the appropriate methods of {@link NavigableMap} (namely {@link // * NavigableMap#subMap(Object, boolean, Object, boolean) subMap()}, {@link // * NavigableMap#tailMap(Object, boolean) tailMap()}, and {@link NavigableMap#headMap(Object, // * boolean) headMap()}) to actually construct the view. Consult these methods for a full // * description of the returned view's behavior. // * // *

Warning: {@code Range}s always represent a range of values using the values' natural // * ordering. {@code NavigableMap} on the other hand can specify a custom ordering via a {@link // * Comparator}, which can violate the natural ordering. Using this method (or in general using // * {@code Range}) with unnaturally-ordered maps can lead to unexpected and undefined behavior. // * // * @since 20.0 // */ // @Beta // @GwtIncompatible // NavigableMap // public static , V> NavigableMap subMap( // NavigableMap map, Range range) { // if (map.comparator() != null // && map.comparator() != Ordering.natural() // && range.hasLowerBound() // && range.hasUpperBound()) { // checkArgument( // map.comparator().compare(range.lowerEndpoint(), range.upperEndpoint()) <= 0, // "map is using a custom comparator which is inconsistent with the natural ordering."); // } // if (range.hasLowerBound() && range.hasUpperBound()) { // return map.subMap( // range.lowerEndpoint(), // range.lowerBoundType() == BoundType.CLOSED, // range.upperEndpoint(), // range.upperBoundType() == BoundType.CLOSED); // } else if (range.hasLowerBound()) { // return map.tailMap(range.lowerEndpoint(), range.lowerBoundType() == BoundType.CLOSED); // } else if (range.hasUpperBound()) { // return map.headMap(range.upperEndpoint(), range.upperBoundType() == BoundType.CLOSED); // } // return checkNotNull(map); // } }