001package org.conqat.lib.commons.collections;
002
003import java.util.Collections;
004import java.util.Set;
005import java.util.function.BiConsumer;
006import java.util.function.BinaryOperator;
007import java.util.function.Function;
008import java.util.function.Supplier;
009import java.util.stream.Collector;
010import java.util.stream.Collectors;
011
012/** A stream {@link Collector} type to create {@link SetMap}s. */
013public class SetMapCollector<T, K, V> implements Collector<T, SetMap<K, V>, SetMap<K, V>> {
014
015        /** Mapper from stream objects to {@link SetMap} keys. */
016        private final Function<T, K> keyMapper;
017
018        /** Mapper from stream objects to {@link SetMap} values. */
019        private final Function<T, V> valueMapper;
020
021        public SetMapCollector(Function<T, K> keyMapper, Function<T, V> valueMapper) {
022                this.keyMapper = keyMapper;
023                this.valueMapper = valueMapper;
024        }
025
026        /**
027         * Collects the stream into a new {@link SetMap} where stream objects are mapped
028         * to {@link SetMap} keys by the given keyMapper and to {@link SetMap} values by
029         * the given valueMapper.
030         */
031        public static <T, K, V> SetMapCollector<T, K, V> collect(Function<T, K> keyMapper, Function<T, V> valueMapper) {
032                return new SetMapCollector<>(keyMapper, valueMapper);
033        }
034
035        /**
036         * Collects the stream into a new {@link SetMap}, grouping stream objects by the
037         * given keyMapper. This works identically to {@link Collectors#groupingBy}.
038         */
039        public static <T, K> SetMapCollector<T, K, T> groupingBy(Function<T, K> keyMapper) {
040                return new SetMapCollector<>(keyMapper, Function.identity());
041        }
042
043        @Override
044        public Supplier<SetMap<K, V>> supplier() {
045                return SetMap::new;
046        }
047
048        @Override
049        public BiConsumer<SetMap<K, V>, T> accumulator() {
050                return (map, element) -> map.add(keyMapper.apply(element), valueMapper.apply(element));
051        }
052
053        @Override
054        public BinaryOperator<SetMap<K, V>> combiner() {
055                return (setMap1, setMap2) -> {
056                        setMap1.addAll(setMap2);
057                        return setMap1;
058                };
059        }
060
061        @Override
062        public Function<SetMap<K, V>, SetMap<K, V>> finisher() {
063                return Function.identity();
064        }
065
066        @Override
067        public Set<Characteristics> characteristics() {
068                return Collections.singleton(Characteristics.IDENTITY_FINISH);
069        }
070}