Grouping by object value, counting and then setting group key by maximum object attribute

前端 未结 4 958
误落风尘
误落风尘 2020-11-28 14:53

I have managed to write a solution using Java 8 Streams API that first groups a list of object Route by its value and then counts the number of objects in each group. It ret

4条回答
  •  情深已故
    2020-11-28 15:38

    You can define an abstract "library" method which combines two collectors into one:

    static  Collector pairing(Collector c1, 
            Collector c2, BiFunction finisher) {
        EnumSet c = EnumSet.noneOf(Characteristics.class);
        c.addAll(c1.characteristics());
        c.retainAll(c2.characteristics());
        c.remove(Characteristics.IDENTITY_FINISH);
        return Collector.of(() -> new Object[] {c1.supplier().get(), c2.supplier().get()},
                (acc, v) -> {
                    c1.accumulator().accept((A1)acc[0], v);
                    c2.accumulator().accept((A2)acc[1], v);
                },
                (acc1, acc2) -> {
                    acc1[0] = c1.combiner().apply((A1)acc1[0], (A1)acc2[0]);
                    acc1[1] = c2.combiner().apply((A2)acc1[1], (A2)acc2[1]);
                    return acc1;
                },
                acc -> {
                    R1 r1 = c1.finisher().apply((A1)acc[0]);
                    R2 r2 = c2.finisher().apply((A2)acc[1]);
                    return finisher.apply(r1, r2);
                }, c.toArray(new Characteristics[c.size()]));
    }
    

    After that the actual operation may look like this:

    Map result = routes.stream()
            .collect(Collectors.groupingBy(Function.identity(),
                pairing(Collectors.maxBy(Comparator.comparingLong(Route::getLastUpdated)), 
                        Collectors.counting(), 
                        (route, count) -> new AbstractMap.SimpleEntry<>(route.get(), count))
                ))
            .values().stream().collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));
    

    Update: such collector is available in my StreamEx library: MoreCollectors.pairing(). Also similar collector is implemented in jOOL library, so you can use Tuple.collectors instead of pairing.

提交回复
热议问题