Одним моим коллегой был обнаружен баг в Stream API: если создавать Map из stream() при помощи .collect(Collectors.toMap()), то всё валится с NPE при значениях null (не ключах).
header.set(Stream.of(Utils.<String, Object>entry("description", status.getDescription())).
collect(utils.entriesToMap()));
Если status.getDescription() == null, то NPE.
Как думаете, знатоки, чем можно объяснить этот феномен?
При заполнении результирующей мапы в реализации коллектора по умолчанию используется метод merge (JDK 1.8b112 java.util.stream.Collectors:1319):
BiConsumer<M, T> accumulator
= (map, element) -> map.merge(keyMapper.apply(element),
valueMapper.apply(element), mergeFunction);
А если заглянуть в реализацию этого метода в классе HashMap, то можно увидеть следующее (java.util.HashMap:1223):
if (value == null)
throw new NullPointerException();
Если не указывать явно, то при использовании Collectors.toMap(), всё собирается в экземпляр класса HashMap.
Варианты решения:
HashMap и TreeMap к таким не относятся, как и все, которые наследуются от интерфейса Map, не переопределяя метод merge, потому что в дефолтной реализации тоже есть строка Objects.requireNonNull(value))самим написать метод добавления новых элементов в мапу и не использовать merge:
.collect(
HashMap::new,
(map, entry) -> map.put(entry.getKey(), entry.getValue()),
HashMap::putAll
);
использовать forEach с сайд-эффектом (не надо так, используйте лучше второй вариант):
Map<K, V> newMap = ...
stream.forEach(e -> newMap.put(e.getKey(), e.getValue()));
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости