class ImmutableMapFactory {

    public static <K, L, V, W> ImmutableMap<L, W> createAndReduceCollisions(
            Map<K, V> baseMap,
            Function<? super K, ? extends L> keyMapper,
            Function<? super V, ? extends W> valueMapper,
            W valueIdentity,
            BinaryOperator<W> collidingKeysAccumulator) {
        Function<Entry<K, V>, Entry<L, W>> entryMapper = e -> new AbstractMap.SimpleEntry<>(
                keyMapper.apply(e.getKey()),
                valueMapper.apply(e.getValue()));

        Collector<Entry<L, W>, ?, W> entriesCollector =
                Collectors.reducing(valueIdentity, Entry::getValue, collidingKeysAccumulator);

        Map<L, W> mutableMap = baseMap.entrySet().stream()
                .map(entryMapper)
                .collect(Collectors.groupingBy(Entry::getKey, entriesCollector));

        return ImmutableMap.copyOf(mutableMap);
    }

}