2017-10-04 3 views
2

Disons que vous avez une liste d'entiers contenant vaues nullJava 8 - Liste de tri des entiers avec des valeurs nulles

List<Integer> integers = Arrays.asList(null, 9, 11, 7, 5, null); 

Maintenant, si vous voulez obtenir une valeur maximale, vous pouvez essayer

OptionalInt max = integers.stream() 
     .mapToInt(Integer::valueOf) 
     .max(); 

Cette fonctionnerait si la liste ne contenait pas de null. Dans notre cas, il y aura une exception NullPointerException. Après quelques recherches, je peux voir une telle solution

Optional<Integer> max = integers.stream() 
     .max(Comparator.nullsFirst(Comparator.naturalOrder())); 

Il fonctionne si l'on considère moins de nulls non NULL. Mais si vous voulez qu'ils soient plus et changer nullsFirst à nullsLast

Optional<Integer> max = integers.stream() 
     .max(Comparator.nullsLast(Comparator.naturalOrder())); 

vous rencontrerez NullPointerException à nouveau.

Je suis intéressant - pourquoi nullsLast ne fonctionne pas dans ce cas étant donné que son doc indique qu'il est null-friendly? Et quelle est la meilleure façon de trier la liste des entiers contenant des zéros?

Merci pour vos idées!

Répondre

2

La documentation des Stream#max états:

Lancers: NullPointerException - si l'élément maximal est nul

Comme vous avez fourni un comparateur qui examinera null comme un élément maximum, c'est pourquoi il jette l'exception.

C'est ce que le stacktrace indique quand il essaie de revenir Optional.of(state); avec state étant null dans votre exemple, et Optional.of jette un NPE si la valeur transmise est null.

Comparator.nullsLast fonctionne très bien, par exemple:

Integer max = 
    Collections.max(integers, Comparator.nullsLast(Comparator.naturalOrder())); 

va bien vous donner null.

0

C'est pas Comparator per se:

List<Integer> result = integers.stream() 
      .sorted(Comparator.nullsLast(Comparator.naturalOrder())) 
      .collect(Collectors.toList()); 
System.out.println(result); // [5, 7, 9, 11, null, null] 

Vous mettez vos valeurs NULL à la fin et ce serait max; appeler max sur un null envoie NullPointerException.

2

Si vous considérez null être plus grande que toute valeur non null, le maximum sera, bien sûr, null lorsque la liste contient une null.

Depuis Stream.max déjà documents qu'il lancera un NullPointerException lorsque le résultat est null, ce comportement est attendu. La logique de conception est similaire à findFirst(), qui a été discuté dans this Q&A.

Notez que même

Optional<Integer> max = integers.stream() 
    .max(Comparator.nullsFirst(Comparator.naturalOrder())); 

peut encore échouer, à savoir si toutes les valeurs sont null. Mais il est inutile d'utiliser une coutume Comparator ici, la solution est-simple:

OptionalInt max = integers.stream() 
    .filter(Objects::nonNull) 
    .mapToInt(Integer::valueOf) 
    .max(); 

Lorsque vous obtenez un vide OptionalInt, vous pouvez toujours tester integers.isEmpty() pour déterminer si tous les éléments étaient null ou il n'y avait pas éléments du tout.