admin管理员组文章数量:1356285
What if I don't want Collectors#toMap
to throw on null values? Java 8
public class CollectorsTest {
@Test
public void collectorsTest() {
List<Map.Entry<String, Object>> params = Arrays.asList(
new AbstractMap.SimpleEntry<>("key1", 1),
new AbstractMap.SimpleEntry<>("key2", null)
);
Map<String, Object> paramMap = toParamMap(params); // throws NPE
}
private static Map<String, Object> toParamMap(List<Map.Entry<String, Object>> params) {
Map<String, Object> paramMap = params.stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
return paramMap;
}
}
What if I don't want Collectors#toMap
to throw on null values? Java 8
public class CollectorsTest {
@Test
public void collectorsTest() {
List<Map.Entry<String, Object>> params = Arrays.asList(
new AbstractMap.SimpleEntry<>("key1", 1),
new AbstractMap.SimpleEntry<>("key2", null)
);
Map<String, Object> paramMap = toParamMap(params); // throws NPE
}
private static Map<String, Object> toParamMap(List<Map.Entry<String, Object>> params) {
Map<String, Object> paramMap = params.stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
return paramMap;
}
}
Share
Improve this question
asked Mar 28 at 11:35
Sergey ZolotarevSergey Zolotarev
1,8691 gold badge11 silver badges31 bronze badges
4
|
2 Answers
Reset to default 6The toMap
collectors don't permit null entry or values. To avoid this you could use forEach
with HashMap.put
as in Hiro Silva's answer.
It is also easy to keep using streams, which might be preferred if making use of parallel or filters on the data. A collector based on HashMap
will permit use of both null keys and values. Stream.collect
handles definition of custom collectors, setting up with arguments to supply a new HashMap
and to add entries to that hashmap:
private static Map<String, Object> toParamMap(List<Map.Entry<String, Object>> params) {
return params.stream()
.collect(HashMap::new,
(map, entry) -> map.put(entry.getKey(), entry.getValue()),
HashMap::putAll);
}
It is cumbersome to write the above each time you might need it, but it can be re-worked to new method returning your own hashmap collector with generic key + value types. This works for handling any collections of Map.Entry using Collector.of
:
public static <K,V> Collector<Map.Entry<K, V>, Map<K, V>, Map<K, V>> toHashMap() {
return Collector.of(HashMap::new,
(map, entry) -> map.put(entry.getKey(), entry.getValue()),
(a,b) -> { a.putAll(b); return a; });
}
Then you can collect streams of Map.Entry
which contains null key+values by adding .collect(toHashMap())
, for example:
Map<String, Object> paramMap = params.stream().collect(toHashMap());
System.out.println(paramMap);
// prints {key1=1, key2=null}
The old HashMap.put()
The modern methods of the standard library, including the methods in the stream package, don’t like nulls as keys or values in maps. Generally for good reasons: nulls are problematic. You may consider a different design where keys with null values are omitted from your map. paramMap.get(yourKey)
will still return the null
that you say you want.
There could still be situations where you got legitimate reasons for wanting one or more null values in the map. To obtain that you may use the classic methods from the introduction of the Java collections framework in Java 1.2. It gets just a little wordier:
private static Map<String, Object> toParamMap(List<Map.Entry<String, Object>> params) {
Map<String, Object> paramMap = new HashMap<>();
params.forEach(param -> paramMap.put(param.getKey(), param.getValue()));
return paramMap;
}
Trying it out with your example:
List<Map.Entry<String, Object>> params = Arrays.asList(
new AbstractMap.SimpleEntry<>("key1", 1),
new AbstractMap.SimpleEntry<>("key2", null)
);
Map<String, Object> paramMap = toParamMap(params);
System.out.println(paramMap);
Output is a map with a null value in it:
{key1=1, key2=null}
本文标签: javaCollectorstoMap No NPEs on null valuesStack Overflow
版权声明:本文标题:java - Collectors#toMap: No NPEs on null values - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744039750a2580443.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
HashMap
that throws it onmerge()
. The class is mandated to do so by theMap
interface (seejava.util.Map#merge
) – Sergey Zolotarev Commented Mar 28 at 12:00toMap
collector doesn’t usemerge
. It did in the first version (Java 8) but nowadays uses an explicitnull
check inside the collector to stay compatible to the first version. It would be easy to create a copy of that implementation and remove the explicitnull
check. – Holger Commented Apr 2 at 12:36