Differenza tra findAny () e findFirst () in Java 8


90

Sto po 'confuso tra la Stream#findAny()e Stream#findFirst()della StreamAPI in Java 8.

Quello che ho capito è che entrambi restituiranno il primo elemento corrispondente dallo stream, ad esempio, se usati insieme al filtro?

Allora, perché due metodi per lo stesso compito? Mi sto perdendo qualcosa?

Risposte:


92

Quello che ho capito è che entrambi restituiranno il primo elemento corrispondente dallo stream, ad esempio, se usati insieme al filtro?

Non è vero. Secondo il javadoc, Stream#findAny():

Restituisce una Optional<T>descrizione di qualche elemento del flusso o un vuoto Optional<T>se il flusso è vuoto. Il comportamento di questa operazione è esplicitamente non deterministico; è libero di selezionare qualsiasi elemento nel flusso. Questo per consentire le massime prestazioni nelle operazioni parallele;

while Stream.findFirst()restituirà una Optional<T>descrizione rigorosa del primo elemento dello stream. La Streamclasse non ha un .findOne()metodo, quindi suppongo tu intendessi .findFirst().


Continuo a non capire, quindi quello che stai dicendo è che anche dopo che filterviene applicato un, findAnypuò restituire qualsiasi elemento, incluso quello che non corrisponde al filtro applicato?
Koray Tugay

@KorayTugay - No, dopo il filtro, qualunque elemento rimanente sia presente, findAnypuò restituire qualsiasi elemento da quello in (una specie di) casuale, in particolare nelle operazioni di flusso parallelo
KrishPrabakar

46

No, entrambi non restituiranno il primo elemento dello Stream.

Da Stream.findAny()(enfasi mia):

Restituisce una Optionaldescrizione di qualche elemento del flusso o un vuoto Optionalse il flusso è vuoto.

Questa è un'operazione da terminale in cortocircuito.

Il comportamento di questa operazione è esplicitamente non deterministico; è libero di selezionare qualsiasi elemento nel flusso . Questo per consentire le massime prestazioni nelle operazioni parallele; il costo è che più invocazioni sulla stessa sorgente potrebbero non restituire lo stesso risultato. (Se si desidera un risultato stabile, utilizzare findFirst()invece.)

Quindi, per dirla più semplicemente, può o non può scegliere il primo elemento dello Stream.

Con l'attuale implementazione specifica di Oracle, credo che restituirà il primo elemento in una pipeline non parallela. Tuttavia, in una pipeline parallela, non sarà sempre (eseguito ad esempio System.out.println(IntStream.range(0, 100).parallel().findAny());, è tornato OptionalInt[50]quando l'ho eseguito). Comunque, non devi fare affidamento su quello.


16

findFirst restituisce i primi elementi del flusso ma findAny è libero di selezionare qualsiasi elemento nel flusso.

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

in modalità parallela l' findAnyordine non garantisce, ma lo findFirstfa.

Ho scritto uno snippet di codice per mostrare la differenza, visitalo


1

Nello stream findFirst e findAny restituiscono il primo elemento e non eseguono il resto, ma in parallelStream, non è possibile dire l'ordine e parallelStream esegue il resto della raccolta.

Riferimento

Tempo 1:25:00


1

Dirò solo che stai attento a findFirst()E findAny()durante l'utilizzo.

A partire dal loro Javadoc ( qui e qui ) entrambi i metodi restituiscono un elemento arbitrario dal flusso - a meno che il flusso non abbia un ordine di incontro , nel qual caso findFirst()restituisce il primo elemento mentre findAny()restituirà qualsiasi elemento.

Supponiamo di avere un listISBN composto da un nome personalizzato e un nome LIBRO. Per uno scenario guarda questo esempio:

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());
    }

Uscita :Optional[Java in Action]

Ci possono essere scenari in cui il nome del libro è lo stesso ma i numeri ISBN sono diversi, in tal caso l'ordinamento e la ricerca del libro possono essere molto simili findAny()e daranno risultati errati. Pensa a uno scenario in cui 5 libri sono denominati "Riferimento Java" ma hanno numeri ISBN diversi e il findFirst()libro per nome avrà lo stesso nome findAny().

Pensa a uno scenario in cui:

 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 |
+-----+------------------+

qui findFirst () e findAny () daranno lo stesso risultato anche se ordinati su BookByName.

Articolo dettagliato:


-1

Quando Streamnon è ordinato, findFirst()e findAny()sono la stessa cosa. Ma quando Streamviene ordinato, findAny()andrà meglio.


Questo non è corretto. Nessuno di questi metodi è "migliore", perché i loro comportamenti e casi d'uso sono completamente diversi. Inoltre, cosa intendi per Streamessere "ordinato"? È sempre ordinato (le operazioni vengono eseguite su dati Streamnello stesso ordine ogni volta che non è parallelizzato), ma forse non ordinate dall'utente.
Jezor
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.