This {@code Collector} uses O(k) memory and takes expected time O(n) (worst-case O(n log
+ * k)), as opposed to e.g. {@code Stream.sorted(comparator).limit(k)}, which currently takes O(n
+ * log n) time and O(n) space.
+ *
+ * @throws IllegalArgumentException if {@code k < 0}
+ */
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static Collector> least(
+ int k, Comparator super T> comparator) {
+ checkNonnegative(k, "k");
+ checkNotNull(comparator);
+ return Collector.of(
+ () -> TopKSelector.least(k, comparator),
+ TopKSelector::offer,
+ TopKSelector::combine,
+ TopKSelector::topK,
+ Collector.Characteristics.UNORDERED);
+ }
+
+ /**
+ * Returns a {@code Collector} that returns the {@code k} greatest (relative to the specified
+ * {@code Comparator}) input elements, in descending order, as an unmodifiable {@code List}. Ties
+ * are broken arbitrarily.
+ *
+ *
This {@code Collector} uses O(k) memory and takes expected time O(n) (worst-case O(n log
+ * k)), as opposed to e.g. {@code Stream.sorted(comparator.reversed()).limit(k)}, which currently
+ * takes O(n log n) time and O(n) space.
+ *
+ * @throws IllegalArgumentException if {@code k < 0}
+ */
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static Collector> greatest(
+ int k, Comparator super T> comparator) {
+ return least(k, comparator.reversed());
+ }
+
/**
* Returns the minimum of the two values. If the values compare as 0, the first is returned.
*
diff --git a/android/guava/src/com/google/common/collect/ImmutableBiMap.java b/android/guava/src/com/google/common/collect/ImmutableBiMap.java
index b40df1b5eb61..d18d5b6f1ff0 100644
--- a/android/guava/src/com/google/common/collect/ImmutableBiMap.java
+++ b/android/guava/src/com/google/common/collect/ImmutableBiMap.java
@@ -29,7 +29,12 @@
import java.util.Collection;
import java.util.Comparator;
import java.util.Map;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
import javax.annotation.CheckForNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
/**
* A {@link BiMap} whose contents will never change, with many other important properties detailed
@@ -42,6 +47,24 @@
@ElementTypesAreNonnullByDefault
public abstract class ImmutableBiMap extends ImmutableMap implements BiMap {
+ /**
+ * Returns a {@link Collector} that accumulates elements into an {@code ImmutableBiMap} whose keys
+ * and values are the result of applying the provided mapping functions to the input elements.
+ * Entries appear in the result {@code ImmutableBiMap} in encounter order.
+ *
+ *
If the mapped keys or values contain duplicates (according to {@link
+ * Object#equals(Object)}), an {@code IllegalArgumentException} is thrown when the collection
+ * operation is performed. (This differs from the {@code Collector} returned by {@link
+ * Collectors#toMap(Function, Function)}, which throws an {@code IllegalStateException}.)
+ */
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static Collector> toImmutableBiMap(
+ Function super T, ? extends K> keyFunction,
+ Function super T, ? extends V> valueFunction) {
+ return CollectCollectors.toImmutableBiMap(keyFunction, valueFunction);
+ }
+
/**
* Returns the empty bimap.
*
@@ -592,5 +615,41 @@ private void readObject(ObjectInputStream stream) throws InvalidObjectException
throw new InvalidObjectException("Use SerializedForm");
}
+ /**
+ * Not supported. Use {@link #toImmutableBiMap} instead. This method exists only to hide {@link
+ * ImmutableMap#toImmutableMap(Function, Function)} from consumers of {@code ImmutableBiMap}.
+ *
+ * @throws UnsupportedOperationException always
+ * @deprecated Use {@link ImmutableBiMap#toImmutableBiMap}.
+ */
+ @Deprecated
+ @DoNotCall("Use toImmutableBiMap")
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static Collector> toImmutableMap(
+ Function super T, ? extends K> keyFunction,
+ Function super T, ? extends V> valueFunction) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Not supported. This method does not make sense for {@code BiMap}. This method exists only to
+ * hide {@link ImmutableMap#toImmutableMap(Function, Function, BinaryOperator)} from consumers of
+ * {@code ImmutableBiMap}.
+ *
+ * @throws UnsupportedOperationException always
+ * @deprecated
+ */
+ @Deprecated
+ @DoNotCall("Use toImmutableBiMap")
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static Collector> toImmutableMap(
+ Function super T, ? extends K> keyFunction,
+ Function super T, ? extends V> valueFunction,
+ BinaryOperator mergeFunction) {
+ throw new UnsupportedOperationException();
+ }
+
private static final long serialVersionUID = 0xdecaf;
}
diff --git a/android/guava/src/com/google/common/collect/ImmutableCollection.java b/android/guava/src/com/google/common/collect/ImmutableCollection.java
index c8167e8f61cc..1da069a2f19b 100644
--- a/android/guava/src/com/google/common/collect/ImmutableCollection.java
+++ b/android/guava/src/com/google/common/collect/ImmutableCollection.java
@@ -36,8 +36,6 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
-import java.util.Spliterator;
-import java.util.Spliterators;
import javax.annotation.CheckForNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -178,11 +176,6 @@ public abstract class ImmutableCollection extends AbstractCollection imple
* These are properties of the collection as a whole; SIZED and SUBSIZED are more properties of
* the spliterator implementation.
*/
- @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
- // @IgnoreJRERequirement is not necessary because this compiles down to a constant.
- // (which is fortunate because Animal Sniffer doesn't look for @IgnoreJRERequirement on fields)
- static final int SPLITERATOR_CHARACTERISTICS =
- Spliterator.IMMUTABLE | Spliterator.NONNULL | Spliterator.ORDERED;
ImmutableCollection() {}
@@ -190,14 +183,6 @@ public abstract class ImmutableCollection extends AbstractCollection imple
@Override
public abstract UnmodifiableIterator iterator();
- @Override
- @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
- @IgnoreJRERequirement // used only from APIs with Java 8 types in them
- // (not used within guava-android as of this writing, but we include it in the jar as a test)
- public Spliterator spliterator() {
- return Spliterators.spliterator(this, SPLITERATOR_CHARACTERISTICS);
- }
-
private static final Object[] EMPTY_ARRAY = {};
@Override
diff --git a/android/guava/src/com/google/common/collect/ImmutableList.java b/android/guava/src/com/google/common/collect/ImmutableList.java
index 9bf354580c1c..940bf96c2967 100644
--- a/android/guava/src/com/google/common/collect/ImmutableList.java
+++ b/android/guava/src/com/google/common/collect/ImmutableList.java
@@ -41,6 +41,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.RandomAccess;
+import java.util.stream.Collector;
import javax.annotation.CheckForNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -62,6 +63,16 @@
public abstract class ImmutableList extends ImmutableCollection
implements List, RandomAccess {
+ /**
+ * Returns a {@code Collector} that accumulates the input elements into a new {@code
+ * ImmutableList}, in encounter order.
+ */
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static Collector> toImmutableList() {
+ return CollectCollectors.toImmutableList();
+ }
+
/**
* Returns the empty immutable list. This list behaves and performs comparably to {@link
* Collections#emptyList}, and is preferable mainly for consistency and maintainability of your
diff --git a/android/guava/src/com/google/common/collect/ImmutableListMultimap.java b/android/guava/src/com/google/common/collect/ImmutableListMultimap.java
index f0d107aa8e04..deab19d8a178 100644
--- a/android/guava/src/com/google/common/collect/ImmutableListMultimap.java
+++ b/android/guava/src/com/google/common/collect/ImmutableListMultimap.java
@@ -33,7 +33,11 @@
import java.util.Comparator;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.function.Function;
+import java.util.stream.Collector;
+import java.util.stream.Stream;
import javax.annotation.CheckForNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
/**
* A {@link ListMultimap} whose contents will never change, with many other important properties
@@ -49,6 +53,78 @@
@ElementTypesAreNonnullByDefault
public class ImmutableListMultimap extends ImmutableMultimap
implements ListMultimap {
+ /**
+ * Returns a {@link Collector} that accumulates elements into an {@code ImmutableListMultimap}
+ * whose keys and values are the result of applying the provided mapping functions to the input
+ * elements.
+ *
+ *
For streams with defined encounter order (as defined in the Ordering section of the {@link
+ * java.util.stream} Javadoc), that order is preserved, but entries are grouped by key.
+ *
+ *
+ */
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static
+ Collector> toImmutableListMultimap(
+ Function super T, ? extends K> keyFunction,
+ Function super T, ? extends V> valueFunction) {
+ return CollectCollectors.toImmutableListMultimap(keyFunction, valueFunction);
+ }
+
+ /**
+ * Returns a {@code Collector} accumulating entries into an {@code ImmutableListMultimap}. Each
+ * input element is mapped to a key and a stream of values, each of which are put into the
+ * resulting {@code Multimap}, in the encounter order of the stream and the encounter order of the
+ * streams of values.
+ *
+ *
+ */
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static
+ Collector> flatteningToImmutableListMultimap(
+ Function super T, ? extends K> keyFunction,
+ Function super T, ? extends Stream extends V>> valuesFunction) {
+ return CollectCollectors.flatteningToImmutableListMultimap(keyFunction, valuesFunction);
+ }
/**
* Returns the empty multimap.
diff --git a/android/guava/src/com/google/common/collect/ImmutableMap.java b/android/guava/src/com/google/common/collect/ImmutableMap.java
index 4ec2f834ef33..79b39b7ade7f 100644
--- a/android/guava/src/com/google/common/collect/ImmutableMap.java
+++ b/android/guava/src/com/google/common/collect/ImmutableMap.java
@@ -46,6 +46,10 @@
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedMap;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
import javax.annotation.CheckForNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -66,6 +70,44 @@
@ElementTypesAreNonnullByDefault
public abstract class ImmutableMap implements Map, Serializable {
+ /**
+ * 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.
+ * Entries appear in the result {@code ImmutableMap} in encounter order.
+ *
+ *
If the mapped keys contain duplicates (according to {@link Object#equals(Object)}, an {@code
+ * IllegalArgumentException} is thrown when the collection operation is performed. (This differs
+ * from the {@code Collector} returned by {@link Collectors#toMap(Function, Function)}, which
+ * throws an {@code IllegalStateException}.)
+ */
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static Collector> toImmutableMap(
+ Function super T, ? extends K> keyFunction,
+ Function super T, ? extends V> valueFunction) {
+ return CollectCollectors.toImmutableMap(keyFunction, valueFunction);
+ }
+
+ /**
+ * 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.
+ *
+ *
If the mapped keys contain duplicates (according to {@link Object#equals(Object)}), the
+ * values are merged using the specified merging function. If the merging function returns {@code
+ * null}, then the collector removes the value that has been computed for the key thus far (though
+ * future occurrences of the key would reinsert it).
+ *
+ *
Entries will appear in the encounter order of the first occurrence of the key.
+ */
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static Collector> toImmutableMap(
+ Function super T, ? extends K> keyFunction,
+ Function super T, ? extends V> valueFunction,
+ BinaryOperator mergeFunction) {
+ return CollectCollectors.toImmutableMap(keyFunction, valueFunction, mergeFunction);
+ }
+
/**
* Returns the empty map. This map behaves and performs comparably to {@link
* Collections#emptyMap}, and is preferable mainly for consistency and maintainability of your
diff --git a/android/guava/src/com/google/common/collect/ImmutableMultiset.java b/android/guava/src/com/google/common/collect/ImmutableMultiset.java
index 9a096d286c35..b5e2e347e1ee 100644
--- a/android/guava/src/com/google/common/collect/ImmutableMultiset.java
+++ b/android/guava/src/com/google/common/collect/ImmutableMultiset.java
@@ -33,6 +33,9 @@
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
+import java.util.function.Function;
+import java.util.function.ToIntFunction;
+import java.util.stream.Collector;
import javax.annotation.CheckForNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -57,6 +60,33 @@
public abstract class ImmutableMultiset extends ImmutableMultisetGwtSerializationDependencies
implements Multiset {
+ /**
+ * Returns a {@code Collector} that accumulates the input elements into a new {@code
+ * ImmutableMultiset}. Elements iterate in order by the first appearance of that element in
+ * encounter order.
+ */
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static Collector> toImmutableMultiset() {
+ return CollectCollectors.toImmutableMultiset(Function.identity(), e -> 1);
+ }
+
+ /**
+ * Returns a {@code Collector} that accumulates elements into an {@code ImmutableMultiset} whose
+ * elements are the result of applying {@code elementFunction} to the inputs, with counts equal to
+ * the result of applying {@code countFunction} to the inputs.
+ *
+ *
If the mapped elements contain duplicates (according to {@link Object#equals}), the first
+ * occurrence in encounter order appears in the resulting multiset, with count equal to the sum of
+ * the outputs of {@code countFunction.applyAsInt(t)} for each {@code t} mapped to that element.
+ */
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static Collector> toImmutableMultiset(
+ Function super T, ? extends E> elementFunction, ToIntFunction super T> countFunction) {
+ return CollectCollectors.toImmutableMultiset(elementFunction, countFunction);
+ }
+
/**
* Returns the empty immutable multiset.
*
diff --git a/android/guava/src/com/google/common/collect/ImmutableRangeMap.java b/android/guava/src/com/google/common/collect/ImmutableRangeMap.java
index 532631617116..72c70b1ae9b5 100644
--- a/android/guava/src/com/google/common/collect/ImmutableRangeMap.java
+++ b/android/guava/src/com/google/common/collect/ImmutableRangeMap.java
@@ -33,7 +33,10 @@
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
+import java.util.function.Function;
+import java.util.stream.Collector;
import javax.annotation.CheckForNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
/**
* A {@link RangeMap} whose contents will never change, with many other important properties
@@ -49,6 +52,19 @@ public class ImmutableRangeMap, V> implements RangeMap, Object> EMPTY =
new ImmutableRangeMap<>(ImmutableList.>>of(), ImmutableList.of());
+ /**
+ * Returns a {@code Collector} that accumulates the input elements into a new {@code
+ * ImmutableRangeMap}. As in {@link Builder}, overlapping ranges are not permitted.
+ */
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static , V>
+ Collector> toImmutableRangeMap(
+ Function super T, Range> keyFunction,
+ Function super T, ? extends V> valueFunction) {
+ return CollectCollectors.toImmutableRangeMap(keyFunction, valueFunction);
+ }
+
/**
* Returns an empty immutable range map.
*
diff --git a/android/guava/src/com/google/common/collect/ImmutableRangeSet.java b/android/guava/src/com/google/common/collect/ImmutableRangeSet.java
index d1f05bc98729..7d08c89e3d39 100644
--- a/android/guava/src/com/google/common/collect/ImmutableRangeSet.java
+++ b/android/guava/src/com/google/common/collect/ImmutableRangeSet.java
@@ -38,6 +38,7 @@
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
+import java.util.stream.Collector;
import javax.annotation.CheckForNull;
/**
@@ -58,6 +59,18 @@ public final class ImmutableRangeSet extends AbstractRange
private static final ImmutableRangeSet> ALL =
new ImmutableRangeSet<>(ImmutableList.of(Range.>all()));
+ /**
+ * Returns a {@code Collector} that accumulates the input elements into a new {@code
+ * ImmutableRangeSet}. As in {@link Builder}, overlapping ranges are not permitted and adjacent
+ * ranges will be merged.
+ */
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static >
+ Collector, ?, ImmutableRangeSet> toImmutableRangeSet() {
+ return CollectCollectors.toImmutableRangeSet();
+ }
+
/**
* Returns an empty immutable range set.
*
diff --git a/android/guava/src/com/google/common/collect/ImmutableSet.java b/android/guava/src/com/google/common/collect/ImmutableSet.java
index 2fd833f230c2..c4631804d6cc 100644
--- a/android/guava/src/com/google/common/collect/ImmutableSet.java
+++ b/android/guava/src/com/google/common/collect/ImmutableSet.java
@@ -38,7 +38,7 @@
import java.util.Iterator;
import java.util.Set;
import java.util.SortedSet;
-import java.util.Spliterator;
+import java.util.stream.Collector;
import javax.annotation.CheckForNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -52,11 +52,18 @@
@SuppressWarnings("serial") // we're overriding default serialization
@ElementTypesAreNonnullByDefault
public abstract class ImmutableSet extends ImmutableCollection implements Set {
+
+ /**
+ * Returns a {@code Collector} that accumulates the input elements into a new {@code
+ * ImmutableSet}. Elements appear in the resulting set in the encounter order of the stream; if
+ * the stream contains duplicates (according to {@link Object#equals(Object)}), only the first
+ * duplicate in encounter order will appear in the result.
+ */
@SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
- // @IgnoreJRERequirement is not necessary because this compiles down to a constant.
- // (which is fortunate because Animal Sniffer doesn't look for @IgnoreJRERequirement on fields)
- static final int SPLITERATOR_CHARACTERISTICS =
- ImmutableCollection.SPLITERATOR_CHARACTERISTICS | Spliterator.DISTINCT;
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static Collector> toImmutableSet() {
+ return CollectCollectors.toImmutableSet();
+ }
/**
* Returns the empty immutable set. Preferred over {@link Collections#emptySet} for code
diff --git a/android/guava/src/com/google/common/collect/ImmutableSetMultimap.java b/android/guava/src/com/google/common/collect/ImmutableSetMultimap.java
index b2d80af4fac6..022a3d40910e 100644
--- a/android/guava/src/com/google/common/collect/ImmutableSetMultimap.java
+++ b/android/guava/src/com/google/common/collect/ImmutableSetMultimap.java
@@ -37,7 +37,11 @@
import java.util.Comparator;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.function.Function;
+import java.util.stream.Collector;
+import java.util.stream.Stream;
import javax.annotation.CheckForNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
/**
* A {@link SetMultimap} whose contents will never change, with many other important properties
@@ -57,6 +61,87 @@
@ElementTypesAreNonnullByDefault
public class ImmutableSetMultimap extends ImmutableMultimap
implements SetMultimap {
+ /**
+ * Returns a {@link Collector} that accumulates elements into an {@code ImmutableSetMultimap}
+ * whose keys and values are the result of applying the provided mapping functions to the input
+ * elements.
+ *
+ *
For streams with defined encounter order (as defined in the Ordering section of the {@link
+ * java.util.stream} Javadoc), that order is preserved, but entries are grouped by key.
+ *
+ *
+ */
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static
+ Collector> toImmutableSetMultimap(
+ Function super T, ? extends K> keyFunction,
+ Function super T, ? extends V> valueFunction) {
+ return CollectCollectors.toImmutableSetMultimap(keyFunction, valueFunction);
+ }
+
+ /**
+ * Returns a {@code Collector} accumulating entries into an {@code ImmutableSetMultimap}. Each
+ * input element is mapped to a key and a stream of values, each of which are put into the
+ * resulting {@code Multimap}, in the encounter order of the stream and the encounter order of the
+ * streams of values.
+ *
+ *
+ */
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static
+ Collector> flatteningToImmutableSetMultimap(
+ Function super T, ? extends K> keyFunction,
+ Function super T, ? extends Stream extends V>> valuesFunction) {
+ return CollectCollectors.flatteningToImmutableSetMultimap(keyFunction, valuesFunction);
+ }
/**
* Returns the empty multimap.
diff --git a/android/guava/src/com/google/common/collect/ImmutableSortedMap.java b/android/guava/src/com/google/common/collect/ImmutableSortedMap.java
index 2bebbe59f1f4..985624968122 100644
--- a/android/guava/src/com/google/common/collect/ImmutableSortedMap.java
+++ b/android/guava/src/com/google/common/collect/ImmutableSortedMap.java
@@ -36,6 +36,10 @@
import java.util.NavigableMap;
import java.util.SortedMap;
import java.util.TreeMap;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
import javax.annotation.CheckForNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -60,6 +64,46 @@
@ElementTypesAreNonnullByDefault
public final class ImmutableSortedMap extends ImmutableMap
implements NavigableMap {
+ /**
+ * Returns a {@link Collector} that accumulates elements into an {@code ImmutableSortedMap} whose
+ * keys and values are the result of applying the provided mapping functions to the input
+ * elements. The generated map is sorted by the specified comparator.
+ *
+ *
If the mapped keys contain duplicates (according to the specified comparator), an {@code
+ * IllegalArgumentException} is thrown when the collection operation is performed. (This differs
+ * from the {@code Collector} returned by {@link Collectors#toMap(Function, Function)}, which
+ * throws an {@code IllegalStateException}.)
+ */
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static
+ Collector> toImmutableSortedMap(
+ Comparator super K> comparator,
+ Function super T, ? extends K> keyFunction,
+ Function super T, ? extends V> valueFunction) {
+ return CollectCollectors.toImmutableSortedMap(comparator, keyFunction, valueFunction);
+ }
+
+ /**
+ * Returns a {@link Collector} that accumulates elements into an {@code ImmutableSortedMap} whose
+ * keys and values are the result of applying the provided mapping functions to the input
+ * elements.
+ *
+ *
If the mapped keys contain duplicates (according to the comparator), the values are merged
+ * using the specified merging function. Entries will appear in the encounter order of the first
+ * occurrence of the key.
+ */
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static
+ Collector> toImmutableSortedMap(
+ Comparator super K> comparator,
+ Function super T, ? extends K> keyFunction,
+ Function super T, ? extends V> valueFunction,
+ BinaryOperator mergeFunction) {
+ return CollectCollectors.toImmutableSortedMap(
+ comparator, keyFunction, valueFunction, mergeFunction);
+ }
/*
* TODO(kevinb): Confirm that ImmutableSortedMap is faster to construct and
@@ -1166,6 +1210,43 @@ private void readObject(ObjectInputStream stream) throws InvalidObjectException
// warning go away (and suppressing would suppress for all nested classes too)
private static final long serialVersionUID = 0;
+ /**
+ * Not supported. Use {@link #toImmutableSortedMap}, which offers better type-safety, instead.
+ * This method exists only to hide {@link ImmutableMap#toImmutableMap} from consumers of {@code
+ * ImmutableSortedMap}.
+ *
+ * @throws UnsupportedOperationException always
+ * @deprecated Use {@link ImmutableSortedMap#toImmutableSortedMap}.
+ */
+ @DoNotCall("Use toImmutableSortedMap")
+ @Deprecated
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static Collector> toImmutableMap(
+ Function super T, ? extends K> keyFunction,
+ Function super T, ? extends V> valueFunction) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Not supported. Use {@link #toImmutableSortedMap}, which offers better type-safety, instead.
+ * This method exists only to hide {@link ImmutableMap#toImmutableMap} from consumers of {@code
+ * ImmutableSortedMap}.
+ *
+ * @throws UnsupportedOperationException always
+ * @deprecated Use {@link ImmutableSortedMap#toImmutableSortedMap}.
+ */
+ @DoNotCall("Use toImmutableSortedMap")
+ @Deprecated
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static Collector> toImmutableMap(
+ Function super T, ? extends K> keyFunction,
+ Function super T, ? extends V> valueFunction,
+ BinaryOperator mergeFunction) {
+ throw new UnsupportedOperationException();
+ }
+
/**
* Not supported. Use {@link #naturalOrder}, which offers better type-safety, instead. This method
* exists only to hide {@link ImmutableMap#builder} from consumers of {@code ImmutableSortedMap}.
diff --git a/android/guava/src/com/google/common/collect/ImmutableSortedMultiset.java b/android/guava/src/com/google/common/collect/ImmutableSortedMultiset.java
index fea0f460e1ac..3660ca596111 100644
--- a/android/guava/src/com/google/common/collect/ImmutableSortedMultiset.java
+++ b/android/guava/src/com/google/common/collect/ImmutableSortedMultiset.java
@@ -33,7 +33,11 @@
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
+import java.util.function.Function;
+import java.util.function.ToIntFunction;
+import java.util.stream.Collector;
import javax.annotation.CheckForNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
/**
* A {@link SortedMultiset} whose contents will never change, with many other important properties
@@ -57,6 +61,67 @@ public abstract class ImmutableSortedMultiset extends ImmutableMultiset
implements SortedMultiset {
// TODO(lowasser): GWT compatibility
+ /**
+ * Returns a {@code Collector} that accumulates the input elements into a new {@code
+ * ImmutableMultiset}. Elements are sorted by the specified comparator.
+ *
+ *
Warning: {@code comparator} should be consistent with {@code equals} as
+ * explained in the {@link Comparator} documentation.
+ */
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static Collector> toImmutableSortedMultiset(
+ Comparator super E> comparator) {
+ return toImmutableSortedMultiset(comparator, Function.identity(), e -> 1);
+ }
+
+ /**
+ * Returns a {@code Collector} that accumulates elements into an {@code ImmutableSortedMultiset}
+ * whose elements are the result of applying {@code elementFunction} to the inputs, with counts
+ * equal to the result of applying {@code countFunction} to the inputs.
+ *
+ *
If the mapped elements contain duplicates (according to {@code comparator}), the first
+ * occurrence in encounter order appears in the resulting multiset, with count equal to the sum of
+ * the outputs of {@code countFunction.applyAsInt(t)} for each {@code t} mapped to that element.
+ */
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static
+ Collector> toImmutableSortedMultiset(
+ Comparator super E> comparator,
+ Function super T, ? extends E> elementFunction,
+ ToIntFunction super T> countFunction) {
+ checkNotNull(comparator);
+ checkNotNull(elementFunction);
+ checkNotNull(countFunction);
+ return Collector.of(
+ () -> TreeMultiset.create(comparator),
+ (multiset, t) -> mapAndAdd(t, multiset, elementFunction, countFunction),
+ (multiset1, multiset2) -> {
+ multiset1.addAll(multiset2);
+ return multiset1;
+ },
+ (Multiset multiset) -> copyOfSortedEntries(comparator, multiset.entrySet()));
+ }
+
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // helper for toImmutableSortedMultiset
+ /*
+ * If we make these calls inline inside toImmutableSortedMultiset, we get an Animal Sniffer error,
+ * despite the @IgnoreJRERequirement annotation there. My assumption is that, because javac
+ * generates a synthetic method for the body of the lambda, the actual method calls that Animal
+ * Sniffer is flagging don't appear inside toImmutableSortedMultiset but rather inside that
+ * synthetic method. By moving those calls to a named method, we're able to apply
+ * @IgnoreJRERequirement somewhere that it will help.
+ */
+ private static void mapAndAdd(
+ T t,
+ Multiset multiset,
+ Function super T, ? extends E> elementFunction,
+ ToIntFunction super T> countFunction) {
+ multiset.add(checkNotNull(elementFunction.apply(t)), countFunction.applyAsInt(t));
+ }
+
/**
* Returns the empty immutable sorted multiset.
*
@@ -682,6 +747,39 @@ private void readObject(ObjectInputStream stream) throws InvalidObjectException
throw new InvalidObjectException("Use SerializedForm");
}
+ /**
+ * Not supported. Use {@link #toImmutableSortedMultiset} instead. This method exists only to hide
+ * {@link ImmutableMultiset#toImmutableMultiset} from consumers of {@code
+ * ImmutableSortedMultiset}.
+ *
+ * @throws UnsupportedOperationException always
+ * @deprecated Use {@link ImmutableSortedMultiset#toImmutableSortedMultiset}.
+ */
+ @DoNotCall("Use toImmutableSortedMultiset.")
+ @Deprecated
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static Collector> toImmutableMultiset() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Not supported. Use {@link #toImmutableSortedMultiset} instead. This method exists only to hide
+ * {@link ImmutableMultiset#toImmutableMultiset} from consumers of {@code
+ * ImmutableSortedMultiset}.
+ *
+ * @throws UnsupportedOperationException always
+ * @deprecated Use {@link ImmutableSortedMultiset#toImmutableSortedMultiset}.
+ */
+ @DoNotCall("Use toImmutableSortedMultiset.")
+ @Deprecated
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static Collector> toImmutableMultiset(
+ Function super T, ? extends E> elementFunction, ToIntFunction super T> countFunction) {
+ throw new UnsupportedOperationException();
+ }
+
/**
* Not supported. Use {@link #naturalOrder}, which offers better type-safety, instead. This method
* exists only to hide {@link ImmutableMultiset#builder} from consumers of {@code
diff --git a/android/guava/src/com/google/common/collect/ImmutableSortedSet.java b/android/guava/src/com/google/common/collect/ImmutableSortedSet.java
index 22660c02c5aa..c6a57824f139 100644
--- a/android/guava/src/com/google/common/collect/ImmutableSortedSet.java
+++ b/android/guava/src/com/google/common/collect/ImmutableSortedSet.java
@@ -36,6 +36,7 @@
import java.util.Iterator;
import java.util.NavigableSet;
import java.util.SortedSet;
+import java.util.stream.Collector;
import javax.annotation.CheckForNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -62,6 +63,19 @@
@ElementTypesAreNonnullByDefault
public abstract class ImmutableSortedSet extends ImmutableSet
implements NavigableSet, SortedIterable {
+ /**
+ * Returns a {@code Collector} that accumulates the input elements into a new {@code
+ * ImmutableSortedSet}, ordered by the specified comparator.
+ *
+ *
If the elements contain duplicates (according to the comparator), only the first duplicate
+ * in encounter order will appear in the result.
+ */
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static Collector> toImmutableSortedSet(
+ Comparator super E> comparator) {
+ return CollectCollectors.toImmutableSortedSet(comparator);
+ }
static RegularImmutableSortedSet emptySet(Comparator super E> comparator) {
if (Ordering.natural().equals(comparator)) {
@@ -765,6 +779,21 @@ Object writeReplace() {
return new SerializedForm(comparator, toArray());
}
+ /**
+ * Not supported. Use {@link #toImmutableSortedSet} instead. This method exists only to hide
+ * {@link ImmutableSet#toImmutableSet} from consumers of {@code ImmutableSortedSet}.
+ *
+ * @throws UnsupportedOperationException always
+ * @deprecated Use {@link ImmutableSortedSet#toImmutableSortedSet}.
+ */
+ @DoNotCall("Use toImmutableSortedSet")
+ @Deprecated
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static Collector> toImmutableSet() {
+ throw new UnsupportedOperationException();
+ }
+
/**
* Not supported. Use {@link #naturalOrder}, which offers better type-safety, instead. This method
* exists only to hide {@link ImmutableSet#builder} from consumers of {@code ImmutableSortedSet}.
diff --git a/android/guava/src/com/google/common/collect/ImmutableTable.java b/android/guava/src/com/google/common/collect/ImmutableTable.java
index 6c8f26dfe0f0..91c9f71a633e 100644
--- a/android/guava/src/com/google/common/collect/ImmutableTable.java
+++ b/android/guava/src/com/google/common/collect/ImmutableTable.java
@@ -32,7 +32,11 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.stream.Collector;
import javax.annotation.CheckForNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
/**
* A {@link Table} whose contents will never change, with many other important properties detailed
@@ -49,6 +53,45 @@
public abstract class ImmutableTable extends AbstractTable
implements Serializable {
+ /**
+ * Returns a {@code Collector} that accumulates elements into an {@code ImmutableTable}. Each
+ * input element is mapped to one cell in the returned table, with the rows, columns, and values
+ * generated by applying the specified functions.
+ *
+ *
The returned {@code Collector} will throw a {@code NullPointerException} at collection time
+ * if the row, column, or value functions return null on any input.
+ */
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static
+ Collector> toImmutableTable(
+ Function super T, ? extends R> rowFunction,
+ Function super T, ? extends C> columnFunction,
+ Function super T, ? extends V> valueFunction) {
+ return TableCollectors.toImmutableTable(rowFunction, columnFunction, valueFunction);
+ }
+
+ /**
+ * Returns a {@code Collector} that accumulates elements into an {@code ImmutableTable}. Each
+ * input element is mapped to one cell in the returned table, with the rows, columns, and values
+ * generated by applying the specified functions. If multiple inputs are mapped to the same row
+ * and column pair, they will be combined with the specified merging function in encounter order.
+ *
+ *
The returned {@code Collector} will throw a {@code NullPointerException} at collection time
+ * if the row, column, value, or merging functions return null on any input.
+ */
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static
+ Collector> toImmutableTable(
+ Function super T, ? extends R> rowFunction,
+ Function super T, ? extends C> columnFunction,
+ Function super T, ? extends V> valueFunction,
+ BinaryOperator mergeFunction) {
+ return TableCollectors.toImmutableTable(
+ rowFunction, columnFunction, valueFunction, mergeFunction);
+ }
+
/**
* Returns an empty immutable table.
*
diff --git a/android/guava/src/com/google/common/collect/Maps.java b/android/guava/src/com/google/common/collect/Maps.java
index 9a385204730a..0664f5dabfb3 100644
--- a/android/guava/src/com/google/common/collect/Maps.java
+++ b/android/guava/src/com/google/common/collect/Maps.java
@@ -65,6 +65,8 @@
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.function.BinaryOperator;
+import java.util.stream.Collector;
import javax.annotation.CheckForNull;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -177,6 +179,48 @@ public static , V> ImmutableMap immutableEnumMap(
return ImmutableEnumMap.asImmutable(enumMap);
}
+ /**
+ * 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}.)
+ */
+ @J2ktIncompatible
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static , V>
+ Collector> toImmutableEnumMap(
+ java.util.function.Function super T, ? extends K> keyFunction,
+ java.util.function.Function super T, ? extends V> valueFunction) {
+ return CollectCollectors.toImmutableEnumMap(keyFunction, valueFunction);
+ }
+
+ /**
+ * 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.
+ */
+ @J2ktIncompatible
+ @SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+ @IgnoreJRERequirement // Users will use this only if they're already using streams.
+ static , V>
+ Collector> toImmutableEnumMap(
+ java.util.function.Function super T, ? extends K> keyFunction,
+ java.util.function.Function super T, ? extends V> valueFunction,
+ BinaryOperator mergeFunction) {
+ return CollectCollectors.toImmutableEnumMap(keyFunction, valueFunction, mergeFunction);
+ }
+
/**
* Creates a mutable, empty {@code HashMap} instance.
*
diff --git a/android/guava/src/com/google/common/collect/MoreCollectors.java b/android/guava/src/com/google/common/collect/MoreCollectors.java
new file mode 100644
index 000000000000..02b254d2d54c
--- /dev/null
+++ b/android/guava/src/com/google/common/collect/MoreCollectors.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2016 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 com.google.common.collect;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.Collections.emptyList;
+
+import com.google.common.annotations.GwtCompatible;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Optional;
+import java.util.stream.Collector;
+import javax.annotation.CheckForNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+/**
+ * Collectors not present in {@code java.util.stream.Collectors} that are not otherwise associated
+ * with a {@code com.google.common} type.
+ *
+ * @author Louis Wasserman
+ */
+@GwtCompatible
+@ElementTypesAreNonnullByDefault
+@SuppressWarnings({"AndroidJdkLibsChecker", "Java7ApiChecker"})
+@IgnoreJRERequirement // Users will use this only if they're already using streams.
+final class MoreCollectors {
+
+ /*
+ * TODO(lowasser): figure out if we can convert this to a concurrent AtomicReference-based
+ * collector without breaking j2cl?
+ */
+ private static final Collector