Java 8 Streams: How to call once the Collection.stream() method and retrieve an array of several aggregate values with different fields

后端 未结 3 419
没有蜡笔的小新
没有蜡笔的小新 2021-02-03 11:18

I\'m starting with the Stream API in Java 8.

Here is my Person object I use:

public class Person {

    private String firstName;
    private String last         


        
3条回答
  •  被撕碎了的回忆
    2021-02-03 11:45

    This is a bit tricky to solve with standard JDK 8 API, which doesn't offer many ways to compose Collector types. If you're willing to use a third party library like jOOλ, you could write:

    Tuple4, Optional, Optional> result =
    Seq.seq(personsList)
       .collect(
           filter(p -> p.getFirstName().equals("John"), count()),
           max(Person::getAge),
           min(Person::getHeight),
           avg(Person::getWeight)
       );
    
    System.out.println(result);
    

    The above yields:

    (2, Optional[35], Optional[1.8], Optional[75.0])
    

    Note, it's using the new Agg.filter() method, which is similar to the JDK 9 Collectors.filtering() method and works like this:

    public static  Collector filter(
        Predicate predicate, Collector downstream) {
        return Collector.of(
            downstream.supplier(),
            (c, t) -> {
                if (predicate.test(t))
                    downstream.accumulator().accept(c, t);
            }, 
            downstream.combiner(),
            downstream.finisher()
        );
    } 
    

    How does collect(collector1, collector2, ...) work?

    If you don't want to use the above third-party library, you can write your own Collector combining utility. An example that combines two collectors into a Tuple2 collector:

    static  Collector, Tuple2> collectors(
        Collector collector1
      , Collector collector2
    ) {
        return Collector., Tuple2>of(
            () -> tuple(
                collector1.supplier().get()
              , collector2.supplier().get()
            ),
            (a, t) -> {
                collector1.accumulator().accept(a.v1, t);
                collector2.accumulator().accept(a.v2, t);
            },
            (a1, a2) -> tuple(
                collector1.combiner().apply(a1.v1, a2.v1)
              , collector2.combiner().apply(a1.v2, a2.v2)
            ),
            a -> tuple(
                collector1.finisher().apply(a.v1)
              , collector2.finisher().apply(a.v2)
            )
        );
    }
    

    Disclaimer: I work for the company behind jOOλ.

提交回复
热议问题