Given a Set
of objects that I want to use as keys, how can I easily get a Map
instance leaving the values as null?
The purpose is to pre-populate the map with keys before determining the values to be stored.
Of course, I could create an empty map, then loop the set of would-be key objects, while doing a put
on each, along with null
as the value.
Set< Month > months = EnumSet.of( Month.MARCH , Month.MAY , Month.JUNE ) ; Map< Month , String > map = new EnumMap<>( Month.class ) ; for( Month month : months ) { map.put( month , null ) ; }
I just wonder if there is a nifty trick to do this with less code. Something like the opposite of Map#keySet
.
Answer
Collectors.toMap()
and the static factory methods like Map.of()
use internally Map.merge
which will throw NPE if key or value is null.
See this post: java-8-nullpointerexception-in-collectors-tomap. And see this issue page on the OpenJDK project: JDK-8148463 Collectors.toMap fails on null values
You could work around by using Stream.collect
with the three args signature as a reduction.
collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner)
Something like:
Set< Month > months = EnumSet.of( Month.MARCH , Month.MAY , Month.JUNE ) ; Map< Month , String > myMap = months.stream() .collect( HashMap::new , ( map , val )-> map.put( val , null ) , HashMap::putAll ); System.out.println(myMap);
See that code run live at IdeOne.com.
But I’m not sure if this is either more readable or more elegant than your approach with the classic for-loop