Функция значения в Collectors.toMap вернула null для одного из элементов. Что произойдёт?
NullPointerException, хотя HashMap null-значения допускает: коллектор использует merge, а он по контракту запрещает null — не отличить от отсутствия ключа.
- Проявляется только на конкретных данных — часто уже в проде
- Обход: отфильтровать null, подставить значение по умолчанию, собрать вручную через collect(HashMap::new, (m, e) -> m.put(...), Map::putAll)
- Или хранить Optional — но это спорно
А ещё null-ключ toMap допускает
Подробно
Причина в реализации: коллектор использует merge, а этот метод по контракту запрещает null-значение, потому что не может отличить его от отсутствия ключа. Ловушка неприятна тем, что проявляется на конкретных данных и часто уже в production. Обходные пути: отфильтровать такие элементы заранее, подставить значение по умолчанию, либо собирать через Collectors.groupingBy или через toMap с явной фабрикой карты и собственной логикой. Стоит помнить и вторую ловушку того же коллектора: при повторяющемся ключе без функции слияния бросается IllegalStateException — и это отдельная от null-значений проблема.
Что хотят услышать
- Исключение и его причина.
- Обходные пути.
Частые ошибки
- Считать, что коллектор ведёт себя так же, как прямое обращение к HashMap.put.
- Путать поведение при дублирующемся ключе и при null-значении.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗В карту попадёт пара с null-значением, ведь HashMap это допускает
- ✗Элемент будет тихо пропущен
- ✓NullPointerException: toMap не допускает null-значений
- ✗Будет брошено IllegalStateException
Что спросят дальше
- Как собрать карту, допускающую null-значения?
- Что делает третий аргумент toMap?
Разбор темы
- Collectors и свёртка
reduce против collect, базовые коллекторы и ловушка toMap, группировка и downstream-коллекторы, характеристики и параллельность.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.