java - sujeto - Encuentra primer elemento por predicado
streams java ejemplo (5)
Acabo de empezar a jugar con Java 8 lambdas e intento implementar algunas de las cosas a las que estoy acostumbrado en los lenguajes funcionales.
Por ejemplo, la mayoría de los lenguajes funcionales tienen algún tipo de función de búsqueda que opera en secuencias o listas que devuelven el primer elemento, para el cual el predicado es true
. La única manera que puedo ver para lograr esto en Java 8 es:
lst.stream()
.filter(x -> x > 5)
.findFirst()
Sin embargo, esto me parece ineficaz, ya que el filtro escaneará toda la lista, al menos a mi entender (lo que podría estar mal). ¿Hay alguna manera mejor?
Sin embargo, esto me parece ineficaz, ya que el filtro escaneará toda la lista
No, no lo hará, se "romperá" tan pronto como se encuentre el primer elemento que satisface el predicado. Puede leer más sobre la pereza en el paquete de flujo javadoc , en particular (énfasis mío):
Muchas operaciones de transmisión, como el filtrado, el mapeo o la eliminación de duplicados, se pueden implementar de forma perezosa, lo que expone las oportunidades de optimización. Por ejemplo, "encontrar la primera cadena con tres vocales consecutivas" no necesita examinar todas las cadenas de entrada. Las operaciones de flujo se dividen en operaciones intermedias (productoras de flujo) y operaciones de terminal (producción de efectos secundarios o de valor). Las operaciones intermedias son siempre perezosas.
A menos que su lista sea realmente enorme (miles de elementos), el uso de flujos aquí es simplemente costoso, e incluso hace que el código sea más difícil de entender.
Nota: java NO es un lenguaje funcional (y jvm no es particularmente adecuado para implementar lenguajes funcionales de manera eficiente).
Mucho más simple y eficiente es (en todos los de Iterable):
for (MyType walk : lst)
if (walk > 5) { do_whatever; break; }
O si quieres saltarte el iterador:
for (int x=0; x<list.size(); x++)
if (list.get(x) > 5 { do_whatever; break; }
En realidad, realmente me pregunto por qué mucha gente sugiere esta compleja y costosa maquinaria de flujos, incluso para cosas triviales como obtener el primer elemento de una matriz. (sí: las matrices todavía son compatibles con Java8).
Además de la respuesta de , si está trabajando con una lista de matrices, en la que no está seguro de que exista el elemento que está buscando, use esto.
Integer a = list.stream()
.peek(num -> System.out.println("will filter " + num))
.filter(x -> x > 5)
.findFirst()
.orElse(null);
Entonces simplemente puedes verificar si a es null
.
No, el filtro no escanea todo el flujo. Es una operación intermedia, que devuelve una secuencia perezosa (en realidad todas las operaciones intermedias devuelven una secuencia perezosa). Para convencerlo, simplemente puede hacer la siguiente prueba:
List<Integer> list = Arrays.asList(1, 10, 3, 7, 5);
int a = list.stream()
.peek(num -> System.out.println("will filter " + num))
.filter(x -> x > 5)
.findFirst()
.get();
System.out.println(a);
Qué salidas:
will filter 1
will filter 10
10
Verá que solo se procesan los dos primeros elementos de la secuencia.
Así que puedes ir con tu enfoque que está perfectamente bien.
return dataSource.getParkingLots().stream().filter(parkingLot -> Objects.equals(parkingLot.getId(), id)).findFirst().orElse(null);
Tuve que filtrar solo un objeto de una lista de objetos. Así que usé esto, espero que ayude.