When filling the resulting map in the collector implementation, the default method is merge (JDK 1.8b112 java.util.stream.Collectors:1319 ):
BiConsumer<M, T> accumulator = (map, element) -> map.merge(keyMapper.apply(element), valueMapper.apply(element), mergeFunction);
And if you look at the implementation of this method in the HashMap class, you can see the following ( java.util.HashMap:1223 ):
if (value == null) throw new NullPointerException();
If you do not explicitly specify, then when using Collectors.toMap() , everything is assembled into an instance of the HashMap class.
Solution options:
- Explicitly specify which Map to use if it does not have such a check (
HashMap and TreeMap do not belong to such, like all that are inherited from the Map interface, without overriding the merge method, because the default implementation also has the string Objects.requireNonNull(value) ) write the method of adding new elements to the map and do not use merge :
.collect( HashMap::new, (map, entry) -> map.put(entry.getKey(), entry.getValue()), HashMap::putAll );
use forEach with a side effect (do not be so, use the second option better):
Map<K, V> newMap = ... stream.forEach(e -> newMap.put(e.getKey(), e.getValue()));