Как преобразовать карту <K, V1> в другую карту <K, V2> с помощью карты функций в Java 8?

Я хочу преобразовать Map<String, Integer> в другой Map<String, Long> с помощью карты функций в Java 8, сопоставляя данные с функциями с помощью ключа на обеих картах. Вы можете предположить, что обе карты имеют одинаковые ключи.

Я попробовал следующий подход:

Map<String, Integer> inputData = new HashMap<>();
inputData.put("A",8);
inputData.put("B",7);
inputData.put("C",6);

Map<String, Function<Integer, Long>> transformers = new HashMap<>();
transformers.put("A", x -> x*2L);
transformers.put("B", x -> x+3L);
transformers.put("C", x -> x+11L);

Map<String, Long> mappedData = inputData.entrySet().stream()
    .map(entry -> new AbstractMap.SimpleEntry<>(
         entry.getKey(),
         transformers.get(entry.getKey()).apply(entry.getValue())))
    .collect(toMap(Map.Entry::getKey, Map.Entry::getValue));

Ожидаемый результат: {A = 16, B = 10, C = 17}.

Есть ли более простой способ выражения "применить карту трансформаторов к отображению соответствия ввода данных по ключу" в API Java Streams?

Ответы

Ответ 1

Вы можете напрямую преобразовать в сборщик:

Map<String, Long> mappedData = inputData.entrySet().stream()
    .collect(toMap(Map.Entry::getKey, 
            entry -> transformers.get(entry.getKey()).apply(entry.getValue())));

Такое решение короче и не создает промежуточные объекты.

Если ваш inputData имел тот же тип значения (Map<String, Long>), вы могли бы выполнить преобразование на месте:

inputData.replaceAll((key, value) -> transformers.get(key).apply(value));

Ответ 2

Вы также можете начать с самой карты transformers, которая выглядит несколько проще:

    Map<String, Long> collect = transformers.entrySet().stream()
            .collect(toMap(Map.Entry::getKey, 
                    e -> e.getValue().apply(inputData.get(e.getKey()))));

Ответ 3

Если одна дополнительная строка вас не беспокоит, попробуйте

Map<String, Long> result = new HashMap<>(); // this line
inputData.forEach((k, v) -> result.put(k, transformers.get(k).apply(v));