2016-04-19 7 views
9

Obwohl ich vermute, die Antwort auf seinen „Es ist nicht angegeben“ ...Wie behandelt Stream.max() Gleichheit?

Wenn es mehr „größte/niedrigste“ Elemente in einem Stream, die die Comparator weitergegeben an die max oder min Methoden gleich betrachtet (liefert 0) , ist es irgendwo angegeben welches Element wird gefunden?

+5

Es scheint kein definiertes Verhalten zu sein. –

+3

Ich könnte mir vorstellen, dass es von der zugrunde liegenden Sammlung abhängt. – munyengm

+2

Side-Frage: Warum ist es wichtig? – Tunaki

Antwort

3

Es ist in der Tat schwierig, eine eindeutige Aussage aus der Dokumentation zu ziehen. Wenn wir versuchen, aus der allgemeinen Beschreibung des "Reduction" -Prozesses und ähnlichen Hinweisen auf die Dokumentation eine Schlussfolgerung zu ziehen, wird es sich immer so anfühlen, als würden wir zu viel Interpretation machen.

Allerdings gibt es ein explicit statement regarding this matter von Brian Goetz, die ganz eine Autorität ist in Bezug auf die Stream-API:

Wenn der Strom (wie die Ströme Sie aus einem Array oder Liste erhalten) bestellt, es gibt die erste Element, das im Falle mehrerer maximaler Elemente maximal ist; Nur wenn der Stream ungeordnet ist, darf ein beliebiges Element ausgewählt werden.

Es ist schade, dass eine solche ausdrückliche Erklärung nicht direkt an der Dokumentation von Stream.max hergestellt, aber zumindest ist es im Einklang mit unserer Erfahrung und das Wissen der Umsetzung (those of us who looked at the source code). Und nicht zu vergessen, praktische Erwägungen, wie es leicht zu sagen ist "Wählen Sie eher als zuerst" über unordered().max(comparator) mit dem aktuellen Stand der Dinge als sagen "erste als alle auswählen" wenn max war erlaubt, ein beliebiges Element an erster Stelle zu wählen .

+2

Ich denke, die explizite Aussage ist nicht zu viel wert, weil es "Stream" -Implementierungen von Drittanbietern gibt, die nicht von den JDK-Entwicklern kontrolliert werden. Und wenn die Javadocs diese Implementierungen nicht einschränken, sind sie frei, diesen Fall so zu behandeln, wie sie wollen. – the8472

+2

@ the8472: wirklich? Nennen Sie mindestens einen ... – Holger

+2

@ the8472: Beachten Sie, dass diese Aussage nicht im leeren Raum steht. Wie bereits in der Antwort erwähnt, gibt es mehrere Aspekte der Dokumentation, die es ermöglichen, eine solche Schlussfolgerung zu ziehen; diese ausdrückliche Aussage ist nur ein guter Beweis dafür, dass wir hier nicht überinterpretieren. – Holger

4

Nach dem Lesen des Quellcodes, denke ich, sollte das erste größte Element wird nach der Abholung Reihenfolge gefunden werden. Wir können den Quellcode der Stream.max(Comparator<? super T> comparator) Check-out, ist die Implementierungsklasse ReferencePipeline.max

@Override 
    public final Optional<P_OUT> max(Comparator<? super P_OUT> comparator) { 
     return reduce(BinaryOperator.maxBy(comparator)); 
    } 

, die Sie sehen können, wenn Sie die Stream.max nennen, rufen Sie meinen die Stream.reduce(BinaryOperator<P_OUT> accumulator)

Und Blick auf den Quellcode von BinaryOperator.maxBy(comparator)

public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) { 
     Objects.requireNonNull(comparator); 
     return (a, b) -> comparator.compare(a, b) >= 0 ? a : b; 
    } 

es ist klar, wenn ab gleich, es gibt a. Wenn also mehrere "größte/niedrigste" Elemente in einem Stream vorhanden sind, sollte das "größte/niedrigste" Element das erste "größte/niedrigste" Element gemäß der Sammlungsreihenfolge sein.

Es gibt ein Beispiel für blow, nur für deine Referenz

 List<Student> list = Arrays.asList(new Student("s1", 1), new Student("s2", 5), new Student("s3", 3), new Student("s4", 5)); 
     // it should be student of 's2' 
     list.stream().max(Comparator.comparing(Student::getScore)); 
     // it should be student of 's4' 
     list.stream().reduce((a, b) -> Comparator.comparing(Student::getScore).compare(a, b) > 0 ? a : b); 
+2

Das hängt wirklich von der Reihenfolge des Streams ab. Weitere Infos hier http://stackoverflow.com/a/29218074/1743880 – Tunaki

+1

@Tunaki: Danke Tunaki, ich lerne viel. :) – Tony

+4

Die Quelle ist informativ, aber nicht normativ. Sie können sich nicht auf Dinge verlassen, wenn sie nicht Teil der Dokumentation sind. – the8472