web-dev-qa-db-fra.com

NullPointerException: l'élément ne peut pas être mappé à une clé nulle

J'ai lu le sujet:

Collectors.groupingBy n'accepte pas les clés nulles

Mais je ne comprends pas comment l'appliquer à mon problème:

mon code:

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

Pour moi MappingEntry::getMilestone peut parfois retourner null. C'est ok pour ma situation mais je vois:

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)

Comment puis-je éviter cette exception?

9
gstackoverflow

Utilisation Collectors.toMap à la place et spécifiez qu'un HashMap est utilisé (car il autorise une clé nulle)

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

)
10
Eugene

Étant donné que vous souhaitez conserver les objets MappingEntry quel que soit le moment où getMilestone() est null ou non null et sachant qu'un NullPointerException sera lancé lorsqu'un contrat particulier n'est pas respecté, alors nous pouvons éviter cela en utilisant une clé de remplacement pour regrouper les objets MappingEntry qui ont un jalon null tout en regroupant le les autres objets MappingEntry tels qu'ils sont censés être.

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

L'astuce consiste à utiliser un opérateur ternaire qui fournit une clé pour regrouper tous les objets MappingEntry qui ont un jalon absent dans un seul groupe et si le jalon n'est pas absent, nous pouvons regrouper par sa valeur comme on peut s'y attendre.

3
Ousmane D.

Vous pouvez utiliser le Collector.of méthode pour spécifier un collecteur personnalisé et utiliser un HashMap pour la carte résultante car selon le Java-8 documents de HashMap

[...] autorise les valeurs nulles et la clé nulle. [...]

Collector.of(
    HashMap::new, 
    (map, e) -> map.computeIfAbsent(e.getMileStone(), k -> new ArrayList<>()).add(e), 
    (left, right) -> {
         right.forEach((key,list) -> left.computeIfAbsent(key, k -> new ArrayList<>()).addAll(list));
         return left;
     })
)
1
Lino