NullPointerException:元素无法映射到null键

gst*_*low 7 java grouping java-8 java-stream

我读过这个话题:

Collectors.groupingBy不接受null键

但我不明白如何将其应用于我的问题:

我的代码:

Map<String, List<MappingEntry>> mappingEntryMap = mapping.getMappingEntries()
                .stream()
                .collect(Collectors.groupingBy(MappingEntry::getMilestone, Collectors.mapping(e -> e, Collectors.toList())));
Run Code Online (Sandbox Code Playgroud)

对我来说MappingEntry::getMilestone有时可以返回null.这对我的情况没问题,但我看到:

Caused by: java.lang.NullPointerException: element cannot be mapped to a null key
    at java.util.Objects.requireNonNull(Objects.java:228)
    at java.util.stream.Collectors.lambda$groupingBy$45(Collectors.java:907)
    at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
    at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
Run Code Online (Sandbox Code Playgroud)

我怎样才能避免这种异常?

Eug*_*ene 10

Collectors.toMap改为使用并指定使用a HashMap(因为它允许一个空键)

 Collectors.toMap(
       MappingEntry::getMilestone,
       x -> {
           List<MappingEntry> list = new ArrayList<>();
           list.add(x);
           return list;
       },
       (left, right) -> {
            left.addAll(right);
            return left;
       },
       HashMap::new

)
Run Code Online (Sandbox Code Playgroud)


Ous*_* D. 8

既然你要保留的MappingEntry对象,而当getMilestone()不为空并且知道一个NullPointerException会被抛出时,在没有特定的合同,然后,满足我们能避免通过使用替代键组MappingEntry其中有一个对象里程碑并将其他MappingEntry对象按原样分组。

Map<String, List<MappingEntry>> mappingEntryMap = 
             mapping.getMappingEntries()
                    .stream()
                    .collect(groupingBy(m -> m.getMilestone() == null ?
                                  "absentMilestone" : m.getMilestone()));
Run Code Online (Sandbox Code Playgroud)

这里的技巧是使用三元运算符,它提供了一个键来将所有没有里程碑的MappingEntry对象分组到一个组中,如果里程碑不存在,那么我们可以按照您的预期按其值进行分组。