Since I didn't find such a library of collectors yet, I'm sharing my first crack at the specific one I've needed. No bells or whistles here! (Such as handling or merging duplicate keys.)
Please feel free to suggest improvements.
/**
* A variant of {@link Collectors#toMap(Function, Function)} for immutable maps.
* <p>
* Note this variant throws {@link IllegalArgumentException} upon duplicate keys, rather than
* {@link IllegalStateException}
*
* @param <T> type of the input elements
* @param <K> output type of the key mapping function
* @param <V> output type of the value mapping function
* @param keyMapper a mapping function to produce keys
* @param valueMapper a mapping function to produce values
*
* @return a {@code Collector} which collects elements into a {@code Map} whose keys and values
* are the result of applying mapping functions to the input elements
*
* @throws IllegalArgumentException upon duplicate keys
*/
public static <T, K, V> Collector<T, ?, ImmutableMap<K,V>> toImmutableMap(
Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends V> valueMapper) {
return new Collector<T, ImmutableMap.Builder<K,V>, ImmutableMap<K,V>>() {
public Supplier<Builder<K, V>> supplier() {
return ImmutableMap.Builder::new;
}
public BiConsumer<Builder<K, V>, T> accumulator() {
return (builder, element) -> {
K key = keyMapper.apply(element);
V value = valueMapper.apply(element);
builder.put(key, value);
};
}
public BinaryOperator<Builder<K, V>> combiner() {
return (b1, b2) -> {
b1.putAll(b2.build());
return b1;
};
}
public Function<Builder<K, V>, ImmutableMap<K, V>> finisher() {
return builder -> builder.build();
}
public Set<Collector.Characteristics> characteristics() {
return ImmutableSet.of();
}
};
}