Das ist mein 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);
ausgabe:
Maximum number in the set is 5
Ich kann keine Unterscheidung zwischen zwei i
im unteren Abschnitt meines Codes machen
Comparator.comparing(i -> i)
kann jemand nett sein und den Unterschied zwischen zwei i
erklären?
Die Methode Comparator.comparing(…)
soll ein Comparator
erstellen, das eine Reihenfolge verwendet, die auf einer zu vergleichenden Eigenschaft der Objekte basiert. Wenn Sie den Lambda-Ausdruck i -> i
verwenden. Hierbei handelt es sich um eine kurze Schreibweise für (int i) -> { return i; }
hier als Eigenschafts-Provider-Funktion. Der resultierende Comparator
vergleicht die Werte selbst. Dies funktioniert, wenn die zu vergleichenden Objekte eine natürliche Ordnung haben wie Integer
.
So
Stream.of(1,2,4,3,5).max(Comparator.comparing(i -> i))
.ifPresent(maxInt->System.out.println("Maximum number in the set is " + maxInt));
macht das gleiche wie
Stream.of(1,2,4,3,5).max(Comparator.naturalOrder())
.ifPresent(maxInt->System.out.println("Maximum number in the set is " + maxInt));
letzteres ist jedoch effizienter, da es als Singleton für alle Typen implementiert wird, die eine natürliche Reihenfolge haben (und Comparable
implementieren).
Der Grund, warum max
überhaupt ein Comparator
erfordert, liegt darin, dass Sie die generische Klasse Stream
verwenden, die beliebige Objekte enthalten kann.
Dies ermöglicht z. Verwenden Sie es wie streamOfPoints.max(Comparator.comparing(p->p.x))
, um den Punkt mit dem größten x
-Wert zu finden, während Point
selbst keine natürliche Reihenfolge hat. Oder machen Sie etwas wie streamOfPersons.sorted(Comparator.comparing(Person::getAge))
.
Wenn Sie die spezialisierte IntStream
verwenden, können Sie die natürliche Reihenfolge direkt verwenden, die wahrscheinlich effizienter ist:
IntStream.of(1,2,4,3,5).max()
.ifPresent(maxInt->System.out.println("Maximum number in the set is " + maxInt));
Um den Unterschied zwischen "natürlicher Ordnung" und einer objektbasierten Reihenfolge zu veranschaulichen:
Stream.of("a","bb","aaa","z","b").max(Comparator.naturalOrder())
.ifPresent(max->System.out.println("Maximum string in the set is " + max));
dies wird gedruckt
Die maximale Zeichenfolge in der Gruppe ist z
als natürliche Reihenfolge von String
s ist die lexikographische Reihenfolge, in der z
größer als b
ist, die größer als a
ist.
Auf der anderen Seite
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));
wird drucken
Die maximale Zeichenfolge im Set ist aaa
as aaa
hat die maximale length aller String
s im Stream. Dies ist der beabsichtigte Anwendungsfall für Comparator.comparing
, der durch die Verwendung von Methodenreferenzen noch lesbarer gemacht werden kann, d. H. Comparator.comparing(String::length)
, was fast für sich selbst spricht…
Diese Funktion (Anmerkung ->
ist für Schließungen und nicht mit =>
zu verwechseln, die zum Vergleich dient)
i -> i
sie müssen lediglich das gesamte Objekt so vergleichen, wie es ist. Wenn ich eine i
habe, müssen Sie i
vergleichen.
Ein weniger triviales Beispiel könnte sein
max(Comparator.comparing(i -> -i))
das gibt Ihnen das Minimum oder
max(Comparator.comparing(i -> Math.abs(100-i))
gibt Ihnen einen Wert, der am weitesten von 100 entfernt ist.
max(Comparator.comparing(i -> i.toString()))
dies gibt Ihnen den maximalen Vergleich als String, d. h. "9"> "10" als String.
Comparator.comparing
erwartet eine Funktion, die das Quellobjekt auf den Wert abbildet, der tatsächlich verglichen wird. Da Sie den zu vergleichenden Wert nicht vorverarbeiten möchten, wird i
einfach auf sich selbst abgebildet.