web-dev-qa-db-fra.com

Trouver Max avec l'expression lambda en Java

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?

13
Kick Buttowski

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 Strings 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 Strings 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…

20
Holger

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.

3
Peter Lawrey

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.

0
Smutje