Unterschied zwischen findAny () und findFirst () in Java 8


88

Ich bin wenig verwirrt zwischen Stream#findAny()und Stream#findFirst()von der StreamAPI in Java 8.

Was ich verstanden habe ist, dass beide das erste übereinstimmende Element aus dem Stream zurückgeben, wenn sie beispielsweise in Verbindung mit einem Filter verwendet werden?

Warum also zwei Methoden für dieselbe Aufgabe? Vermisse ich etwas

Antworten:


91

Was ich verstanden habe ist, dass beide das erste übereinstimmende Element aus dem Stream zurückgeben, wenn sie beispielsweise in Verbindung mit einem Filter verwendet werden?

Das ist nicht wahr. Nach Angaben des Javadoc Stream#findAny():

Gibt ein Optional<T>beschreiben einige Elemente des Stroms, oder ein leere , Optional<T>wenn der Strom ist leer. Das Verhalten dieser Operation ist explizit nicht deterministisch. Es ist frei, ein beliebiges Element im Stream auszuwählen. Dies soll eine maximale Leistung im Parallelbetrieb ermöglichen.

while Stream.findFirst()gibt eine Optional<T>Beschreibung zurück, die ausschließlich das erste Element des Streams beschreibt. Die StreamKlasse hat keine .findOne()Methode, also haben Sie es wohl gemeint .findFirst().


Ich verstehe immer noch nicht, also was Sie sagen werden , ist auch nach einem filterangewendet wird, findAnyjedes Element zurückkehren können, einschließlich , dass nicht der Filter angewendet überein?
Koray Tugay

@KorayTugay - Nein, nach dem Filter können alle verbleibenden Elemente, unabhängig davon, welche Elemente vorhanden sind, findAnyjedes Element (zufällig) zurückgeben, insbesondere bei parallelen Stream-Operationen
KrishPrabakar,

45

Nein, beide geben das erste Element des Streams nicht zurück.

Von Stream.findAny()(Hervorhebung von mir):

Gibt ein Optionalbeschreibendes Element des Streams zurück oder ein leeres, Optionalwenn der Stream leer ist.

Dies ist ein Kurzschluss des Terminals.

Das Verhalten dieser Operation ist explizit nicht deterministisch. Es ist frei, ein beliebiges Element im Stream auszuwählen . Dies soll eine maximale Leistung im Parallelbetrieb ermöglichen. Die Kosten bestehen darin, dass mehrere Aufrufe an derselben Quelle möglicherweise nicht dasselbe Ergebnis liefern. (Wenn ein stabiles Ergebnis gewünscht wird, verwenden Sie findFirst()stattdessen.)

Einfacher ausgedrückt kann es das erste Element des Streams auswählen oder nicht.

Ich glaube, dass mit der aktuellen Oracle-spezifischen Implementierung das erste Element in einer nicht parallelen Pipeline zurückgegeben wird. In einer parallelen Pipeline wird dies jedoch nicht immer der Fall sein (zum Beispiel System.out.println(IntStream.range(0, 100).parallel().findAny());wird es ausgeführt, OptionalInt[50]wenn ich es ausgeführt habe). Darauf dürfen Sie sich jedenfalls nicht verlassen.


16

findFirst gibt die ersten Elemente des Streams zurück, aber findAny kann jedes Element im Stream auswählen.

List<String> lst1 = Arrays.asList("Jhonny", "David", "Jack", "Duke", "Jill","Dany","Julia","Jenish","Divya");
List<String> lst2 = Arrays.asList("Jhonny", "David", "Jack", "Duke", "Jill","Dany","Julia","Jenish","Divya");

Optional<String> findFirst = lst1.parallelStream().filter(s -> s.startsWith("D")).findFirst();
Optional<String> fidnAny = lst2.parallelStream().filter(s -> s.startsWith("J")).findAny();

System.out.println(findFirst.get()); //Always print David
System.out.println(fidnAny.get()); //Print Jack/Jill/Julia :behavior of this operation is explicitly nondeterministic

1

im parallelen Modus findAnygarantiert das nicht die Reihenfolge, aber das findFirsttut.

Ich habe ein Code-Snippet geschrieben, um den Unterschied zu zeigen. Besuchen Sie es


1

In stream findFirst und findAny wird das erste Element zurückgegeben und der Rest nicht ausgeführt. In parallelStream ist es jedoch nicht passabel, die Reihenfolge anzugeben, und parallelStream führt den Rest der Sammlung aus.

Referenz

Zeit 1:25:00


1

Ich werde nur sagen, dass Vorsicht vor findFirst()und findAny()während der Verwendung.

Ab ihrem Javadoc ( hier und hier ) geben beide Methoden ein beliebiges Element aus dem Stream zurück - es sei denn, der Stream hat eine Begegnungsreihenfolge . In diesem Fall wird findFirst()das erste Element zurückgegeben, während findAny()ein beliebiges Element zurückgegeben wird.

Angenommen, wir haben einen benutzerdefinierten listISBN- und BOOK-Namen. Ein Szenario finden Sie in diesem Beispiel:

public class Solution {
   private Integer ISBN;
   private String BookName;

public Solution(int i, String string) {
    ISBN =i;
    BookName = string;
}
//getters and setters
}

public static void main(String[] args) {
        List<Solution> Library = Arrays.asList(new Solution(12,"Java in Action"),new Solution(13,"Java 8"),new Solution(15,"Java 8 Features"),new Solution(16,"Java in Action"));
 System.out.println(Library.stream()
        .map(p->p.getBookName())
        .sorted(Comparator.reverseOrder())
        .findFirst());
    }

Ausgabe :Optional[Java in Action]

Es kann Szenarien geben, in denen der Buchname identisch ist, die ISBN-Nummern jedoch unterschiedlich sind. In diesem Fall kann das Sortieren und Auffinden des Buches dem Buch sehr ähnlich sein findAny()und zu falschen Ergebnissen führen. Stellen Sie sich ein Szenario vor, in dem 5 Bücher den Namen "Java Reference" tragen, aber unterschiedliche ISBN-Nummern haben und das findFirst()Buch nach Namen dasselbe ergibt wie findAny().

Stellen Sie sich ein Szenario vor, in dem:

 ISBN    Name Of book
+-----+------------------+
| 100 | Java-8 in Action |
+-----+------------------+
| 101 | Java-8 in Action |
+-----+------------------+
| 102 | Java-8 in Action |
+-----+------------------+
| 103 | Java-8 in Action |
+-----+------------------+
| 104 | Java-8 in Action |
+-----+------------------+

Hier liefern findFirst () und findAny () das gleiche Ergebnis, auch wenn sie nach BookByName sortiert sind.

Ausführlicher Artikel:


0

Wann Streamist ungeordnet findFirst()und findAny()sind gleich. Aber wann Streambestellt wird, findAny()wird besser.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.