C'est mon code
List<Integer> ints = Stream.of(1,2,4,3,5).collect(Collectors.toList());
Integer maxInt = ints.stream()
.max(Comparator.comparing(i -> i))
.get();
System.out.println("Maximum number in the set is " + maxInt);
sortie:
Maximum number in the set is 5
Je ne peux pas distinguer deux i
dans la section ci-dessous de mon code
Comparator.comparing(i -> i)
quelqu'un peut-il être gentil et expliquer la différence entre deux i
?
La méthode Comparator.comparing(…)
permet de créer une Comparator
qui utilise un ordre basé sur une propriété des objets à comparer. Lorsque vous utilisez l'expression lambda i -> i
, qui est une écriture courte pour (int i) -> { return i; }
ici, en tant que fonction de fournisseur de propriétés, la variable Comparator
résultante compare les valeurs elle-même. Cela fonctionne quand les objets à comparer ont un ordre naturel comme Integer
a.
Alors
Stream.of(1,2,4,3,5).max(Comparator.comparing(i -> i))
.ifPresent(maxInt->System.out.println("Maximum number in the set is " + maxInt));
fait la même chose que
Stream.of(1,2,4,3,5).max(Comparator.naturalOrder())
.ifPresent(maxInt->System.out.println("Maximum number in the set is " + maxInt));
bien que ce dernier soit plus efficace, il est implémenté en tant que singleton pour tous les types qui ont un ordre naturel (et implémentent Comparable
).
La raison pour laquelle max
nécessite au minimum Comparator
est que vous utilisez la classe générique Stream
qui peut contenir des objets arbitraires.
Cela permet, par exemple l'utiliser comme streamOfPoints.max(Comparator.comparing(p->p.x))
pour trouver le point avec la plus grande valeur x
alors que Point
lui-même n'a pas d'ordre naturel. Ou faire quelque chose comme streamOfPersons.sorted(Comparator.comparing(Person::getAge))
.
Lorsque vous utilisez la IntStream
spécialisée, vous pouvez utiliser directement l'ordre naturel, ce qui est susceptible d'être plus efficace:
IntStream.of(1,2,4,3,5).max()
.ifPresent(maxInt->System.out.println("Maximum number in the set is " + maxInt));
Pour illustrer la différence entre «ordre naturel» et un ordre basé sur la propriété:
Stream.of("a","bb","aaa","z","b").max(Comparator.naturalOrder())
.ifPresent(max->System.out.println("Maximum string in the set is " + max));
cela va imprimer
La chaîne maximale dans l'ensemble est z
comme l'ordre naturel de String
s est l'ordre lexicographique où z
est supérieur à b
qui est supérieur à a
D'autre part
Stream.of("a","bb","aaa","z","b").max(Comparator.comparing(s->s.length()))
.ifPresent(max->System.out.println("Maximum string in the set is " + max));
imprimera
La chaîne maximale dans l'ensemble est aaa
comme aaa
a le maximum length de tous les String
s du flux. C’est le cas d’utilisation prévu de Comparator.comparing
qui peut être rendu encore plus lisible lors de l’utilisation de références de méthodes, c’est-à-dire Comparator.comparing(String::length)
qui parle presque de lui-même…
Cette fonction (note ->
est pour les fermetures et ne doit pas être confondu avec =>
qui est pour la comparaison)
i -> i
signifie simplement que vous devez comparer l'objet entier tel qu'il est. c'est-à-dire que si j'ai une i
, vous devez comparer i
Un exemple moins trivial pourrait être
max(Comparator.comparing(i -> -i))
qui vous donnera le minimum ou
max(Comparator.comparing(i -> Math.abs(100-i))
vous donne une valeur qui est la plus éloignée de 100.
max(Comparator.comparing(i -> i.toString()))
ce qui vous donnera le maximum de comparaison en tant que chaîne, c'est-à-dire "9"> "10" en tant que chaîne.
Comparator.comparing
attend une fonction qui mappe l'objet source à la valeur qui est comparée - dans votre cas, comme vous ne souhaitez pas prétraiter la valeur à comparer, i
est simplement mappé sur lui-même.