Class MoreCollectors

java.lang.Object
com.google.mu.util.stream.MoreCollectors

public final class MoreCollectors extends Object
Static utilities pertaining to Collector in addition to relevant utilities in JDK and Guava.
Since:
5.2
  • Method Details

    • mapping

      public static <F, T, T1, R> Collector<F,?,R> mapping(Function<? super F,? extends T> inputMapper, Collector<T,?,T1> collector, Function<? super T1,? extends R> outputMapper)
      Returns a collector that uses inputMapper function to transform each input, and finally uses outputMapper to transform the output of the given collector.
      Since:
      6.0
    • mapping

      public static <T, A, B, R> Collector<T,?,R> mapping(Function<? super T,? extends Both<? extends A,? extends B>> mapper, BiCollector<A,B,R> downstream)
      Analogous to Collectors.mapping(), applies a mapping function to each input element before accumulation, except that the mapper function returns a pair of elements, which are then accumulated by a BiCollector.

      For example, you can parse key-value pairs in the form of "k1=v1,k2=v2" with:

      
       Substring.first(',')
           .repeatedly()
           .split("k1=v2,k2=v2")
           .collect(
               mapping(
                   s -> first('=').split(s).orElseThrow(...),
                   toImmutableSetMultimap()));
       
    • flatMapping

      public static <T, K, V, R> Collector<T,?,R> flatMapping(Function<? super T,? extends BiStream<? extends K,? extends V>> flattener, BiCollector<K,V,R> downstream)
      Similar but slightly different than Collectors.flatMapping(java.util.function.Function<? super T, ? extends java.util.stream.Stream<? extends U>>, java.util.stream.Collector<? super U, A, R>), returns a Collector that first flattens the input stream of pairs (as opposed to single elements) and then collects the flattened pairs with the downstream BiCollector.
    • flatteningMaps

      public static <K, V, R> Collector<Map<K,V>,?,R> flatteningMaps(BiCollector<K,V,R> downstream)
      Returns a Collector that flattens the input Map entries and collects them using the downstream BiCollector.

      For example, you can flatten a list of multimaps:

      
       ImmutableMap<EmployeeId, Task> billableTaskAssignments = projects.stream()
           .map(Project::getTaskAssignments)
           .collect(flatteningMaps(ImmutableMap::toImmutableMap)));
       
    • toMap

      public static <T, K, V, M extends Map<K, V>> Collector<T,?,M> toMap(Function<? super T,? extends K> keyFunction, Function<? super T,? extends V> valueFunction, Supplier<? extends M> mapSupplier)
      Returns a Collector that extracts the keys and values through the given keyFunction and valueFunction respectively, and then collects them into a mutable Map created by mapSupplier.

      Duplicate keys will cause IllegalArgumentException to be thrown, with the offending key reported in the error message.

      Null keys and values are discouraged but supported as long as the result Map supports them. Thus this method can be used as a workaround of the toMap(Supplier) JDK bug that fails to support null values.

      Since:
      5.9
    • toListAndThen

      public static <T> Collector<T,?,List<T>> toListAndThen(Consumer<? super List<T>> arranger)
      Returns a collector that collects input elements into a list, which is then arranged by the arranger function before being wrapped as immutable list result. List elements are not allowed to be null.

      Example usages:

      • stream.collect(toListAndThen(Collections::reverse)) to collect to reverse order.
      • stream.collect(toListAndThen(Collections::shuffle)) to collect and shuffle.
      • stream.collect(toListAndThen(Collections::sort)) to collect and sort.
    • collectingAndThen

      public static <T, A, B, R> Collector<T,?,R> collectingAndThen(Collector<T,?,? extends Both<? extends A,? extends B>> upstream, BiFunction<? super A,? super B,? extends R> finisher)
      Returns a Collector that maps the result of upstream collector using the finisher BiFunction. Useful when combined with collectors like partitioningBy(java.util.function.Predicate<? super E>, java.util.stream.Collector<E, ?, ? extends R>).

      For example:

      
       collectingAndThen(partitioningBy(Person::isGood), (good, evil) -> ...)
       
      Since:
      8.1
    • combining

      public static <T, R> FixedSizeCollector<T,?,R> combining(BiFunction<? super T,? super T,? extends R> mapper)
      Returns a collector that collects the only two elements from the input and transforms them using the mapper function. If there are fewer or more elements in the input, IllegalArgumentExceptioin is thrown.

      To handle the size() != 2 case, consider to use the MoreCollections.findOnlyElements() method, which returns Optional.

      Since:
      6.6
    • combining

      public static <T, R> FixedSizeCollector<T,?,R> combining(MapFrom3<? super T,? extends R> mapper)
      Returns a collector that collects the only three elements from the input and transforms them using the mapper function. If there are fewer or more elements in the input, IllegalArgumentExceptioin is thrown.

      To handle the size() != 3 case, consider to use the MoreCollections.findOnlyElements() method, which returns Optional.

      Since:
      6.6
    • combining

      public static <T, R> FixedSizeCollector<T,?,R> combining(MapFrom4<? super T,? extends R> mapper)
      Returns a collector that collects the only four elements from the input and transforms them using the mapper function. If there are fewer or more elements in the input, IllegalArgumentExceptioin is thrown.

      To handle the size() != 4 case, consider to use the MoreCollections.findOnlyElements() method, which returns Optional.

      Since:
      6.6
    • combining

      public static <T, R> FixedSizeCollector<T,?,R> combining(MapFrom5<? super T,? extends R> mapper)
      Returns a collector that collects the only five elements from the input and transforms them using the mapper function. If there are fewer or more elements in the input, IllegalArgumentExceptioin is thrown.

      To handle the size() != 5 case, consider to use the MoreCollections.findOnlyElements() method, which returns Optional.

      Since:
      6.6
    • combining

      public static <T, R> FixedSizeCollector<T,?,R> combining(MapFrom6<? super T,? extends R> mapper)
      Returns a collector that collects the only six elements from the input and transforms them using the mapper function. If there are fewer or more elements in the input, IllegalArgumentExceptioin is thrown.

      To handle the size() != 6 case, consider to use the MoreCollections.findOnlyElements() method, which returns Optional.

      Since:
      6.6
    • combining

      public static <T, R> FixedSizeCollector<T,?,R> combining(MapFrom7<? super T,? extends R> mapper)
      Returns a collector that collects the only seven elements from the input and transforms them using the mapper function. If there are fewer or more elements in the input, IllegalArgumentExceptioin is thrown.

      To handle the size() != 7 case, consider to use the MoreCollections.findOnlyElements() method, which returns Optional.

      Since:
      7.2
    • combining

      public static <T, R> FixedSizeCollector<T,?,R> combining(MapFrom8<? super T,? extends R> mapper)
      Returns a collector that collects the only eight elements from the input and transforms them using the mapper function. If there are fewer or more elements in the input, IllegalArgumentExceptioin is thrown.

      To handle the size() != 8 case, consider to use the MoreCollections.findOnlyElements() method, which returns Optional.

      Since:
      7.2
    • onlyElement

      public static <T, R> FixedSizeCollector<T,?,R> onlyElement(Function<? super T,? extends R> mapper)
      Returns collector that collects the single element from the input. It will throw otherwise.
      Since:
      5.4
    • onlyElements

      public static <T, R> FixedSizeCollector<T,?,R> onlyElements(BiFunction<? super T,? super T,? extends R> mapper)
      Since:
      5.3
    • onlyElements

      public static <T, R> FixedSizeCollector<T,?,R> onlyElements(MapFrom3<? super T,? extends R> mapper)
      Since:
      5.3
    • onlyElements

      public static <T, R> FixedSizeCollector<T,?,R> onlyElements(MapFrom4<? super T,? extends R> mapper)
      Since:
      5.3
    • onlyElements

      public static <T, R> FixedSizeCollector<T,?,R> onlyElements(MapFrom5<? super T,? extends R> mapper)
      Since:
      5.3
    • onlyElements

      public static <T, R> FixedSizeCollector<T,?,R> onlyElements(MapFrom6<? super T,? extends R> mapper)
      Since:
      5.3
    • onlyElements

      public static <T, R> FixedSizeCollector<T,?,R> onlyElements(MapFrom7<? super T,? extends R> mapper)
      Since:
      7.2
    • onlyElements

      public static <T, R> FixedSizeCollector<T,?,R> onlyElements(MapFrom8<? super T,? extends R> mapper)
      Since:
      7.2
    • switching

      @SafeVarargs public static <T, R> Collector<T,?,R> switching(FixedSizeCollector<T,?,R> firstCase, FixedSizeCollector<T,?,R>... moreCases)
      Returns a Collector that will collect the input elements using the first of [firstCase, moreCases...] that matches the input elements.

      For example, you may have a table name that could be in one of several formats:

      • database.schema.table;
      • schema.table in the current database;
      • table in the current database and current schema;
      To handle these different cases, you can do:
      
       Substring.first('.').repeatedly().split(tableName)
           .collect(
               switching(
                   onlyElements((db, schema, table) -> ...),
                   onlyElements((schema, table) -> ...),
                   onlyElements(table -> ...)));
       
      Since:
      5.4
    • partitioningBy

      public static <E, R> Collector<E,?,Both<R,R>> partitioningBy(Predicate<? super E> predicate, Collector<E,?,? extends R> downstream)
      Returns a collector that partitions the incoming elements into two groups: elements that match predicate, and those that don't.

      For example:

      
       candidates
           .collect(partitioningBy(Candidate::isEligible, toImmutableList()))
           .andThen((eligible, ineligible) -> ...);
       

      Compared to Collectors.partitioningBy(java.util.function.Predicate<? super T>), which returns a Map<Boolean, V>, the syntax is easier to be chained without needing an intermediary Map local variable.

      Type Parameters:
      E - the input element type
      R - the result type of downstream collector.
      Since:
      6.0
    • partitioningBy

      public static <E, A1, A2, T, F> Collector<E,?,Both<T,F>> partitioningBy(Predicate<? super E> predicate, Collector<E,A1,? extends T> downstreamIfTrue, Collector<E,A2,? extends F> downstreamIfFalse)
      Returns a collector that partitions the incoming elements into two groups: elements that match predicate, and those that don't, and use downstreamIfTrue and downstreamIfFalse respectively to collect the elements.

      For example:

      
       candidates
           .collect(partitioningBy(Candidate::isPrimary, toOptional(), toImmutableList()))
           .andThen((primary, secondaries) -> ...);
       

      Compared to Collectors.partitioningBy(java.util.function.Predicate<? super T>), which returns a Map<Boolean, V>, the syntax is easier to be chained without needing an intermediary Map local variable; and you can collect the two partitions to different types.

      Type Parameters:
      E - the input type
      A1 - the accumulator type of the downstreamIfTrue collector
      A2 - the accumulator type of the downstreamIfFalse collector
      T - the result type of the downstreamIfTrue collector
      F - the result type of the downstreamIfFalse collector
      Since:
      6.5
    • minMax

      public static <T> Collector<T,?,BiOptional<T,T>> minMax(Comparator<? super T> comparator)
      Returns a collector that collects the minimum and maximum elements from the input elements. the result BiOptional, if present, contains the pair of (min, max).

      Null elements are supported as long as comparator supports them.

      Since:
      6.0
    • allMin

      public static <T, R> Collector<T,?,R> allMin(Comparator<? super T> comparator, Collector<? super T,?,R> downstream)
      Returns a Collector that collects all of the least (relative to the specified Comparator) input elements, in encounter order, using the downstream collector.

      For example:

      
       Stream.of("foo", "bar", "banana", "papaya")
           .collect(allMin(comparingInt(String::length), toImmutableList()))
       // returns {"foo", "bar"}
       
      Since:
      5.6
    • allMax

      public static <T, R> Collector<T,?,R> allMax(Comparator<? super T> comparator, Collector<? super T,?,R> downstream)
      Returns a Collector that collects all of the greatest (relative to the specified Comparator) input elements, in encounter order, using the downstream collector.

      For example:

      
       Stream.of("foo", "quux", "banana", "papaya")
           .collect(greatest(comparingInt(String::length), toImmutableList()))
       // returns {"banana", "papaya"}
       
      Since:
      5.6