package com.googlecode.totallylazy.transducers; import com.googlecode.totallylazy.Sequence; import com.googlecode.totallylazy.Sequences; import com.googlecode.totallylazy.functions.Function1; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public interface GroupByTransducer<T, K> extends Transducer<T, Group<K, T>> { Function1<? super T, ? extends K> keyExtractor(); static <T, K> GroupByTransducer<T, K> groupByTransducer(Function1<? super T, ? extends K> keyExtractor) {return () -> keyExtractor;} @Override default Receiver<T> apply(Receiver<Group<K, T>> receiver) { return new Receiver<T>() { private final Map<K, Group<K, T>> groups = new ConcurrentHashMap<>(); @Override public State start() { receivers().each(Receiver::start); return receiver.start(); } @Override public State next(T item) { groups.computeIfAbsent(keyExtractor().apply(item), k -> { Group<K, T> group = new Group<>(k); receiver.next(group); return group; }).next(item); return State.Continue; } @Override public State error(Throwable throwable) { receivers().each(o -> o.error(throwable)); return receiver.error(throwable); } @Override public void finish() { receivers().each(Receiver::finish); receiver.finish(); } private Sequence<Receiver<T>> receivers() { return Sequences.sequence(groups.values()); } }; } }