public final class CollectorUtils
extends java.lang.Object
Collector instances useful in conjunction with Java streams.| Modifier and Type | Method and Description |
|---|---|
static <T> java.util.stream.Collector<T,?,java.util.List<T>> |
conditionalCollector(java.util.function.Predicate<T> shouldAddToGroup)
When using the Java
Collectors.groupingBy(...) methods, you might come across a situation where you
want to include a grouping with a key in the resulting map, but don't want to include particular elements in the
collection it maps to. |
static <T,R extends java.util.Collection<T>> |
conditionalCollector(java.util.function.Predicate<T> shouldAddToGroup,
java.util.function.Supplier<R> supplier)
When using the Java
Collectors.groupingBy(...) methods, you might come across a situation where you
want to include a grouping with a key in the resulting map, but don't want to include particular elements in the
collection it maps to. |
static <E extends java.lang.Enum<E>> |
toEnumSet(java.lang.Class<E> enumClass)
Builds a
Collector that constructs an EnumSet, and accumulates enumerated values into
it. |
static <T> java.util.stream.Collector<T,?,java.util.List<T>> |
toListWithDefault(T defaultElement)
Returns a
Collector that will add a default element into a resulting collection, if it would have
otherwise been empty. |
static <K,V> java.util.stream.Collector<java.util.Map.Entry<K,V>,?,java.util.Map<K,V>> |
toMapFromEntry()
Sometimes it is convenient to stream through the entries of a map.
|
static <T> java.util.stream.Collector<T,?,java.util.List<java.util.List<T>>> |
toPartitionedList(int partitionSize)
Builds a
Collector that accumulates a stream of elements into a list of lists of those elements,
each limited to the passed partitionSize. |
static <T,R> java.util.stream.Collector<T,java.util.List<java.util.List<T>>,java.util.List<R>> |
toPartitionedList(int partitionSize,
java.util.function.Function<java.util.List<java.util.List<T>>,java.util.List<R>> finisher)
Builds a
Collector that accumulates a stream of elements into a list of arbitrary objects of type
<R>, into which those elements are accumulated. |
static <T> java.util.stream.Collector<T,?,java.util.stream.Stream<java.util.List<T>>> |
toPartitionedStream(int partitionSize)
Builds a
Collector that accumulates a stream of elements into a stream of lists of those elements,
each limited to the passed partitionSize. |
static <T> java.util.stream.Collector<T,?,java.util.Set<T>> |
toSetWithDefault(T defaultElement)
Returns a
Collector that will add a default element into a resulting collection, if it would have
otherwise been empty. |
static java.util.stream.Collector<java.lang.Integer,?,java.lang.StringBuilder> |
toStringBuilder()
Builds a
Collector that can be useful in dealing with strings as a stream of characters. |
static <T> java.util.stream.Collector<T,?,java.util.Collection<T>> |
toSynchronizedCollection(java.util.function.Supplier<java.util.Collection<T>> wrappedCollectionSupplier)
Builds a
Collector that accumulates into a collection supplied by wrappedCollectionSupplier,
which will be wrapped by a synchronized collection. |
static <T> java.util.stream.Collector<T,?,java.util.List<T>> |
toSynchronizedList()
Builds a
Collector that accumulates into an synchronized list. |
static <T> java.util.stream.Collector<T,?,java.util.Set<T>> |
toSynchronizedSet()
Builds a
Collector that accumulates into an synchronized set. |
static <T> java.util.stream.Collector<T,?,java.util.Collection<T>> |
toUnmodifiableCollection(java.util.function.Supplier<java.util.Collection<T>> wrappedCollectionSupplier)
Builds a
Collector that accumulates into a collection supplied by wrappedCollectionSupplier,
which will be wrapped by a unmodifiable collection. |
static <T> java.util.stream.Collector<T,?,java.util.List<T>> |
toUnmodifiableList()
Builds a
Collector that accumulates into an unmodifiable list. |
static <T> java.util.stream.Collector<T,?,java.util.Set<T>> |
toUnmodifiableSet()
Builds a
Collector that accumulates into an unmodifiable set. |
static <T,R extends java.util.Collection<T>> |
withDefault(T defaultElement,
java.util.function.Supplier<R> supplier)
Returns a
Collector that will add a default element into a resulting collection, if it would have
otherwise been empty. |
public static <T> java.util.stream.Collector<T,?,java.util.List<T>> conditionalCollector(java.util.function.Predicate<T> shouldAddToGroup)
Collectors.groupingBy(...) methods, you might come across a situation where you
want to include a grouping with a key in the resulting map, but don't want to include particular elements in the
collection it maps to. An example of this might be that you have a collection of customer order objects you need
to report on. The report should include all orders for a particular customer, but only those line items whose
price is over a certain amount. Here is an example of how this might work:
Collection<OrderLineItem> customerLineItems = ...
Predicate<OrderLineItem> priceLevelPredicate = PredicateUtils.gt(100, OrderLineItem::getPrice);
Map<String, List<OrderLineItem>> itemsByOrderId = customerLineItems.stream()
.collect(groupingBy(OrderLineItem::getOrderId, CollectorUtils.conditionalCollector(priceLevelPredicate)));
This conditional collector can be used with any of the Collectors.groupingBy(...) overloads that
take a downstream Collector. It can also be used along with the Java Collectors.mapping(...)
method, which would apply a transformation to the element before applying the conditional collector.
This method is equivalent to calling conditionalCollector(Predicate, Supplier) passing ArrayList::new
as the supplier.
T - The type of the input elements being streamed.shouldAddToGroup - A predicate to filter the elements from the collection value associated with each key in
map returned by the Java Collectors.groupingBy(...) collector.public static <T,R extends java.util.Collection<T>> java.util.stream.Collector<T,R,R> conditionalCollector(java.util.function.Predicate<T> shouldAddToGroup,
java.util.function.Supplier<R> supplier)
Collectors.groupingBy(...) methods, you might come across a situation where you
want to include a grouping with a key in the resulting map, but don't want to include particular elements in the
collection it maps to. An example of this might be that you have a collection of customer order objects you need
to report on. The report should include all orders for a particular customer, but only those line items whose
price is over a certain amount. Here is an example of how this might work:
Collection<OrderLineItem> customerLineItems = ...
Predicate<OrderLineItem> priceLevelPredicate = PredicateUtils.gt(100, OrderLineItem::getPrice);
Map<String, Set<OrderLineItem>> itemsByOrderId = customerLineItems.stream()
.collect(groupingBy(OrderLineItem::getOrderId, CollectorUtils.conditionalCollector(priceLevelPredicate, HashSet::new)));
This conditional collector can be used with any of the Collectors.groupingBy(...) overloads that
take a downstream Collector. It can also be used along with the Java Collectors.mapping(...)
method, which would apply a transformation to the element before applying the conditional collector.T - The type of the input elements being streamed.R - The type of collection to group into, as specified by the passed supplier.shouldAddToGroup - A predicate to filter the elements from the collection value associated with each key in
map returned by the Java Collectors.groupingBy(...) collector.supplier - A supplier of the collection, into which elements are to be grouped.public static <K,V> java.util.stream.Collector<java.util.Map.Entry<K,V>,?,java.util.Map<K,V>> toMapFromEntry()
Map<String, TestEnum> enumMap = Arrays.stream(TestEnum.values())
.collect(toMap(TestEnum::name, Function.identity());
Then, if we stream over the entries of this map:
enumMap.entrySet().stream()
.map(MapperUtils.pairOf(Map.Entry::getValue, Map.Entry::getKey))
.collect(CollectorUtils.toMapFromEntry());
We can collect the transformed entries of the map back into a different one. The MapperUtils.pairOf(...)
method creates an apache commons lang Pair object, which implements the Map.Entry
interface. This allows us to call this method, switch the key and value around, and create a new, reversed
map where the key has now become the value, and vice versa. This is just a contrived example, but dealing with
Map.Entry and/or Pair instances in streams, and the ability to convert them back into
transformed maps can be very useful.K - The Map.Entry key type.V - The Map.Entry value type.public static <T> java.util.stream.Collector<T,?,java.util.stream.Stream<java.util.List<T>>> toPartitionedStream(int partitionSize)
Collector that accumulates a stream of elements into a stream of lists of those elements,
each limited to the passed partitionSize. For example, given the following code:
IntStream.range(0, 100)
.boxed()
.collect(CollectorUtils.toPartitionedStream(10))
.forEach(System.out::println);
After execution of this code, the output would be:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
[30, 31, 32, 33, 34, 35, 36, 37, 38, 39]
[40, 41, 42, 43, 44, 45, 46, 47, 48, 49]
[50, 51, 52, 53, 54, 55, 56, 57, 58, 59]
[60, 61, 62, 63, 64, 65, 66, 67, 68, 69]
[70, 71, 72, 73, 74, 75, 76, 77, 78, 79]
[80, 81, 82, 83, 84, 85, 86, 87, 88, 89]
[90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
T - The type of the elements in the collection to be partitioned.partitionSize - The size limit for each partitioned list.public static <T> java.util.stream.Collector<T,?,java.util.List<java.util.List<T>>> toPartitionedList(int partitionSize)
Collector that accumulates a stream of elements into a list of lists of those elements,
each limited to the passed partitionSize. For example, given the following code:
IntStream.range(0, 100)
.boxed()
.collect(CollectorUtils.toPartitionedList(10))
.forEach(System.out::println);
After execution of this code, the output would be:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
[30, 31, 32, 33, 34, 35, 36, 37, 38, 39]
[40, 41, 42, 43, 44, 45, 46, 47, 48, 49]
[50, 51, 52, 53, 54, 55, 56, 57, 58, 59]
[60, 61, 62, 63, 64, 65, 66, 67, 68, 69]
[70, 71, 72, 73, 74, 75, 76, 77, 78, 79]
[80, 81, 82, 83, 84, 85, 86, 87, 88, 89]
[90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
T - The type of the elements in the collection to be partitioned.partitionSize - The size limit for each partitioned list.public static <T,R> java.util.stream.Collector<T,java.util.List<java.util.List<T>>,java.util.List<R>> toPartitionedList(int partitionSize,
java.util.function.Function<java.util.List<java.util.List<T>>,java.util.List<R>> finisher)
Collector that accumulates a stream of elements into a list of arbitrary objects of type
<R>, into which those elements are accumulated. For example, this method is used in the implementation of
DblStreamUtils.toPartitionedDblList(double[], int):
public static List<double[]> toPartitionedDblList(double[] doubles, int partitionSize) {
return defaultDblStream(doubles)
.boxed()
.collect(toPartitionedList(partitionSize, DblStreamUtils::toListOfArrays));
}
private static List<double[]> toListOfArrays(List<List<Double>> partitions) {
return partitions.stream()
.map(DblStreamUtils::listToArray)
.collect(toList());
}
The DblStreamUtils.toPartitionedDblList(double[], int) method partitions an array of doubles into a
List<double[]>.T - The type of the elements in the collection to be partitioned.R - The type of the object, into which a partition of elements will be accumulated.partitionSize - The size limit for the maximum number of elements that may be accumulated into each object
of type <R>.finisher - A finisher function that accumulates each partition List<T> into an object of type
<R>.public static java.util.stream.Collector<java.lang.Integer,?,java.lang.StringBuilder> toStringBuilder()
Collector that can be useful in dealing with strings as a stream of characters. For example,
given the following code:
System.out.println("test123".codePoints()
.filter(Character::isDigit)
.boxed()
.collect(CollectorUtils.toStringBuilder()));
After execution of this code, the output would be:
123
If it was necessary, for performance reasons, to keep the stream as an IntStream, and not use the
IntStream.boxed() method, a similar collector could be created like this:
System.out.println("test123".codePoints()
.filter(Character::isDigit)
.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append));
However, in most cases, the difference in execution speed will be negligible.public static <E extends java.lang.Enum<E>> java.util.stream.Collector<E,?,java.util.EnumSet<E>> toEnumSet(java.lang.Class<E> enumClass)
Collector that constructs an EnumSet, and accumulates enumerated values into
it.E - The type of the enum class, for which to build a collector.enumClass - The class of the enum, for which to build a collector.public static <T> java.util.stream.Collector<T,?,java.util.List<T>> toListWithDefault(T defaultElement)
Collector that will add a default element into a resulting collection, if it would have
otherwise been empty. This overload defaults the collection type to a List, and is equivalent to
either withDefault(Object, Supplier) passing ArrayList::new as the Supplier.
For example:
List<String> strings = Collections.singletonList('').stream()
.filter(PredicateUtils.not(String::isEmpty))
.collect(CollectorUtils.toListWithDefault('default'));
The strings collection would contain one string, 'default' after executing this code.T - The type of the input elements being streamed.defaultElement - A default element to be added to a resulting collection.public static <T> java.util.stream.Collector<T,?,java.util.Set<T>> toSetWithDefault(T defaultElement)
Collector that will add a default element into a resulting collection, if it would have
otherwise been empty. This overload defaults the collection type to a Set, and is equivalent to
either withDefault(Object, Supplier) passing HashSet::new as the Supplier.
For example:
Set<String> strings = Collections.singletonList('').stream()
.filter(PredicateUtils.not(String::isEmpty))
.collect(CollectorUtils.toSetWithDefault('default'));
The strings set would contain one string, 'default' after executing this code.T - The type of the input elements being streamed.defaultElement - A default element to be added to a resulting collection.public static <T,R extends java.util.Collection<T>> java.util.stream.Collector<T,?,R> withDefault(T defaultElement,
java.util.function.Supplier<R> supplier)
Collector that will add a default element into a resulting collection, if it would have
otherwise been empty. For example:
List<String> strings = Collections.singletonList('').stream()
.filter(PredicateUtils.not(String::isEmpty))
.collect(CollectorUtils.withDefault('default', LinkedList::new));
The strings linked list would contain one string, 'default' after executing this code.T - The type of the input elements being streamed.R - The type of collection to group into, as specified by the passed supplier.defaultElement - A default element to be added to a resulting collection.supplier - A supplier of the collection, into which elements are to be added.public static <T> java.util.stream.Collector<T,?,java.util.List<T>> toUnmodifiableList()
Collector that accumulates into an unmodifiable list.T - The type of the input elements being streamed.public static <T> java.util.stream.Collector<T,?,java.util.Set<T>> toUnmodifiableSet()
Collector that accumulates into an unmodifiable set.T - The type of the input elements being streamed.public static <T> java.util.stream.Collector<T,?,java.util.Collection<T>> toUnmodifiableCollection(java.util.function.Supplier<java.util.Collection<T>> wrappedCollectionSupplier)
Collector that accumulates into a collection supplied by wrappedCollectionSupplier,
which will be wrapped by a unmodifiable collection.T - The type of the input elements being streamed.wrappedCollectionSupplier - A supplier of a collection instance, that will be wrapped by an unmodifiable
collection.public static <T> java.util.stream.Collector<T,?,java.util.List<T>> toSynchronizedList()
Collector that accumulates into an synchronized list.T - The type of the input elements being streamed.public static <T> java.util.stream.Collector<T,?,java.util.Set<T>> toSynchronizedSet()
Collector that accumulates into an synchronized set.T - The type of the input elements being streamed.public static <T> java.util.stream.Collector<T,?,java.util.Collection<T>> toSynchronizedCollection(java.util.function.Supplier<java.util.Collection<T>> wrappedCollectionSupplier)
Collector that accumulates into a collection supplied by wrappedCollectionSupplier,
which will be wrapped by a synchronized collection.T - The type of the input elements being streamed.wrappedCollectionSupplier - A supplier of a collection instance, that will be wrapped by an synchronized
collection.