Custom map collector

I have a collection consisting of Map<Pair<DateTime, String>, List<Entity>>, which was previously grouped using streams. Entityis a simple class with property intand getValue().

Now I want to combine the values Entityusing my simple EntityAccumulatormodification like the previous map on Map<Pair<DateTime, String>, EntityAccumulator>. The only way I can achieve this, as I understand it, is to create your own custom collector, however I stuck with a method finisher()that should return Pair.

Or maybe there is an easier way to achieve the result I want?

Streamprocessing

 Map<Pair<DateTime, String>, EntityAccumulator> collect = entities.stream()
                .collect(Collectors.groupingBy(entity-> Pair.of(entity.getTimestamp(), entity.getName())))
                .entrySet().stream()
                .collect(new EntityCollector()));

EntityAccumulator

private static class EntityAccumulator {

        private int result = 0.0;

        public EntityAccumulator() { }

        public EntityAccumulator(int result) {
            this.result = result;
        }

        public void calculate(Entity entity) {
            result += entity.getValue();
        }

        public EntityAccumulatoradd(EntityAccumulator other) {
            return new EntityAccumulator(this.result + other.result);
        }
}

collector

public class EntityCollector implements Collector<Map.Entry<Pair<DateTime, String>, List<Entity>>, EntityAccumulator, Map.Entry<Pair<DateTime, String>, EntityAccumulator>> {

    @Override
    public Supplier<EntityAccumulator> supplier() {
        return EntityAccumulator::new;
    }

    @Override
    public BiConsumer<EntityAccumulator, Map.Entry<Pair<DateTime, String>, List<Entity>>> accumulator() {
        return (result, pairListEntry) -> pairListEntry.getValue().forEach(result::calculate);
    }

    @Override
    public BinaryOperator<EntityAccumulator> combiner() {
        return EntityAccumulator::add;
    }

    @Override
    public Function<EntityAccumulator, Map.Entry<Pair<DateTime, String>, EntityAccumulator>> finisher() {
        return (k) -> {
            return  null; // ??? HELP HERE 
        }
    }


    @Override
    public Set<Characteristics> characteristics() {
        return EnumSet.of(Characteristics.UNORDERED);
    }
}
+4
1

-,

Map<Pair<DateTime, String>, Double> collect = entities.stream()
    .collect(Collectors.groupingBy(
        entity -> Pair.of(entity.getTimestamp(), entity.getName()),
        Collectors.summingDouble(Entity::getValue)));

Map<Pair<DateTime, String>, Integer> collect = entities.stream()
    .collect(Collectors.groupingBy(
        entity -> Pair.of(entity.getTimestamp(), entity.getName()),
        Collectors.summingInt(Entity::getValue)));

. int result = 0.0 .

-, , Collector groupingBy collector. , Map, Map.Entry.

( ), , summingInt summingDouble.

, , . EntityAccumulator , Map.Entry<Pair<DateTime, String>, EntityAccumulator>.

, Collector . Collector.of, , Collector.

, EntityAccumulator (, result int 0.0 ),

Map<Pair<DateTime, String>, Integer> collect = entities.stream()
    .collect(Collectors.groupingBy(
        entity -> Pair.of(entity.getTimestamp(), entity.getName()),
        Collector.of(EntityAccumulator::new,
                     EntityAccumulator::calculate,
                     EntityAccumulator::add,
                     ea -> ea.result,
                     Collector.Characteristics.UNORDERED)));

, . , ,

Map<Pair<DateTime, String>, Integer> collect = entities.stream()
    .collect(Collectors.groupingBy(e -> Pair.of(e.getTimestamp(), e.getName())))
    .entrySet().stream()
    .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().stream().collect(
        Collector.of(EntityAccumulator::new,
                     EntityAccumulator::calculate,
                     EntityAccumulator::add,
                     ea -> ea.result,
                     Collector.Characteristics.UNORDERED))));

, , . , , .

+5

Source: https://habr.com/ru/post/1665624/


All Articles