Diferencia entre findAny () y findFirst () en Java 8

90

Estoy un poco confundido entre Stream#findAny()y Stream#findFirst()de la StreamAPI en Java 8.

Lo que entendí es que ambos devolverán el primer elemento coincidente de la secuencia, por ejemplo, cuando se usa junto con el filtro.

Entonces, ¿por qué dos métodos para la misma tarea? ¿Me estoy perdiendo de algo?

Mandeep Rajpal
fuente

Respuestas:

92

Lo que entendí es que ambos devolverán el primer elemento coincidente de la secuencia, por ejemplo, cuando se usa junto con el filtro.

Eso no es cierto. De acuerdo con el javadoc, Stream#findAny():

Devuelve un elemento que Optional<T>describe algún elemento del flujo, o un vacío Optional<T>si el flujo está vacío. El comportamiento de esta operación es explícitamente no determinista; es libre de seleccionar cualquier elemento en la secuencia. Esto es para permitir el máximo rendimiento en operaciones paralelas;

while Stream.findFirst()devolverá una Optional<T>descripción estrictamente del primer elemento de la secuencia. La Streamclase no tiene un .findOne()método, así que supongo que te refieres .findFirst().

Konstantin Yovkov
fuente
Todavía no entiendo, así que lo que está diciendo es que incluso después de que filterse aplique un, ¿ findAnypuede devolver cualquier elemento, incluido el que no coincide con el filtro aplicado?
Koray Tugay
@KorayTugay - No, después del filtro, los elementos restantes que estén presentes, findAnypueden devolver cualquier elemento de eso en (algo así) aleatorio, particularmente en operaciones de flujo paralelo
KrishPrabakar
46

No, ambos no devolverán el primer elemento del Stream.

De Stream.findAny()(énfasis mío):

Devuelve un elemento queOptional describe algún elemento del flujo, o un vacío Optionalsi el flujo está vacío.

Esta es una operación de terminal de cortocircuito.

El comportamiento de esta operación es explícitamente no determinista; es libre de seleccionar cualquier elemento en la secuencia . Esto es para permitir el máximo rendimiento en operaciones paralelas; el costo es que varias invocaciones en la misma fuente pueden no devolver el mismo resultado. (Si se desea un resultado estable, utilice findFirst()en su lugar).

Entonces, para decirlo de manera más simple, puede o no elegir el primer elemento del Stream.

Con la implementación específica actual de Oracle, creo que devolverá el primer elemento en la tubería no paralela. Sin embargo, en una canalización paralela, no siempre (ejecutar, por ejemplo System.out.println(IntStream.range(0, 100).parallel().findAny());, regresó OptionalInt[50]cuando lo ejecuté). De todos modos, debe no confiar en eso.

Atún
fuente
16

findFirst devuelve los primeros elementos de la secuencia, pero findAny es libre de seleccionar cualquier elemento de la secuencia.

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
Amir
fuente
1

en modo paralelo findAny, no garantiza el orden, pero findFirstsí.

Escribí un fragmento de código para mostrar la diferencia, visítalo.

jiahut
fuente
1

En el flujo findFirst y findAny devuelven el primer elemento y no ejecutan el resto, pero en paraleloStream, no es aceptable decir el orden y paraleloStream ejecuta el resto de la colección.

Referencia

Hora 1:25:00

emon
fuente
1

Solo diré que tenga cuidado con findFirst()Y findAny()mientras lo usa.

A partir de su Javadoc ( aquí y aquí ) ambos métodos devuelven un elemento arbitrario de la secuencia, a menos que la secuencia tenga un orden de encuentro , en cuyo caso findFirst()devuelve el primer elemento mientras findAny()que devolverá cualquier elemento.

Supongamos que tenemos un listISBN y un nombre de LIBRO personalizados. Para ver un escenario, mire este ejemplo:

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

Salida :Optional[Java in Action]

Puede haber situaciones en las que el nombre del libro es el mismo pero los números de ISBN son diferentes; en ese caso, ordenar y encontrar el libro puede ser muy similar findAny()y producirá un resultado incorrecto. Piense en un escenario en el que 5 libros se denominan "Referencia de Java" pero tienen diferentes números ISBN y el resultado del findFirst()libro por nombre es el mismo que findAny().

Piense en un escenario en el que:

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

aquí findFirst () y findAny () darán el mismo resultado incluso si se ordenan en BookByName.

Artículo detallado:

Vishwa Ratna
fuente
-1

Cuando Streamestá desordenado findFirst()y findAny()son lo mismo. Pero cuando Streamse ordene, findAny()será mejor.

logbasex
fuente
Esto es incorrecto. Ninguno de estos métodos es "mejor", porque sus comportamientos y casos de uso son completamente diferentes. Además, ¿qué quiere decir con un Streamser "ordenado"? Siempre está ordenado (las operaciones se ejecutan Streamen el mismo orden cada vez que no está en paralelo), pero quizás no las ordena el usuario.
Jezor