Как собрать элементы Stream в HashMap?

«Как собрать элементы Stream в HashMap?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Для сбора Stream в HashMap используется коллектор Collectors.toMap().

Базовый пример: Преобразование списка строк в Map<String, Integer>, где ключ — строка, значение — её длина.

List<String> list = Arrays.asList("a", "bb", "ccc");
Map<String, Integer> map = list.stream()
    .collect(Collectors.toMap(
        Function.identity(), // s -> s  (ключ)
        String::length       // значение
    )); // Результат: {"a"=1, "bb"=2, "ccc"=3}

Важные нюансы и расширенные сценарии:

  1. Уникальность ключей: Если ключи дублируются, будет выброшено IllegalStateException. Для обработки коллизий используйте функцию слияния (merge function):
    // Подсчёт вхождений строк: при дубликате ключа значения суммируются
    Map<String, Integer> frequencyMap = stream.collect(
        Collectors.toMap(
            k -> k,
            v -> 1,
            (oldVal, newVal) -> oldVal + newVal // Функция слияния
        )
    );
  2. Конкретная реализация Map: Чтобы получить не HashMap, а, например, LinkedHashMap (сохраняет порядок добавления), укажите поставщик (supplier):
    Map<String, Integer> linkedMap = stream.collect(
        Collectors.toMap(
            keyMapper,
            valueMapper,
            mergeFunction,
            LinkedHashMap::new // Поставщик конкретной реализации Map
        )
    );