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?
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
)
É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.
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;
})
)