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}