Estaba jugando con Java 8 lambdas para filtrar fácilmente las colecciones. Pero no encontré una forma concisa de recuperar el resultado como una nueva lista dentro de la misma declaración. Aquí está mi enfoque más conciso hasta ahora:
List<Long> sourceLongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);
List<Long> targetLongList = new ArrayList<>();
sourceLongList.stream().filter(l -> l > 100).forEach(targetLongList::add);
Los ejemplos en la red no respondieron a mi pregunta porque se detienen sin generar una nueva lista de resultados. Debe haber una manera más concisa. Lo que habría esperado, que la Stream
clase tiene métodos como toList()
, toSet()
...
¿Hay alguna manera de que las variables targetLongList
puedan ser asignadas directamente por la tercera línea?
collections
lambda
java-8
java-stream
Daniel K.
fuente
fuente
sourceLongList
esCollection.removeIf(…)
conveniente.List<Long> targetLongList = sourceLongList.stream().collect(Collectors.toList());
Respuestas:
Lo que está haciendo puede ser la forma más sencilla, siempre que su transmisión permanezca secuencial; de lo contrario, tendrá que poner una llamada a secuencial () antes
forEach
.[Edición posterior: la razón por la cual la llamada a secuencial () es necesaria es que el código tal como está (
forEach(targetLongList::add)
) sería picante si la secuencia fuera paralela. Incluso entonces, no logrará el efecto deseado, ya queforEach
es explícitamente no determinista, incluso en una secuencia secuencial no se garantiza el orden del procesamiento del elemento. Tendría que usarforEachOrdered
para garantizar un pedido correcto. La intención de los diseñadores de Stream API es que utilizará el recopilador en esta situación, como se muestra a continuación.]Una alternativa es
fuente
toList
. Esto se realiza mediante la colocación de la siguiente entre las importaciones del archivo:static import java.util.stream.Collectors.toList;
. Entonces la llamada por cobrar se lee solo.collect(toList())
.Collectors
clase en Preferencias -> Java -> Editor -> Content Assist -> Favoritos . Después de esto, solo tiene que escribirtoLi
al presionar Ctr + Espacio para que el IDE se completetoList
y agregue la importación estática.IntStream
y algunos otros casi pero no delStream
todo no tienen elcollect(Collector)
método y primero tendrá que llamarIntStream.boxed()
para convertirlos en normalesStream
. Por otra parte, tal vez solo quierastoArray()
.sequential()
antesforEach
o usar 'forEachOrdered`Actualizado:
Otro enfoque es usar
Collectors.toList
:Solución anterior:
Otro enfoque es usar
Collectors.toCollection
:fuente
Collectors::toList
javadoc: "No hay garantías sobre el tipo, mutabilidad, serialización o seguridad de subprocesos de la Lista devuelta; si se requiere más control sobre la Lista devuelta, úselatoCollection(Supplier)
".Me gusta usar un método util que devuelve un recopilador para
ArrayList
cuando eso es lo que quiero.Creo que usar la solución
Collectors.toCollection(ArrayList::new)
es demasiado ruidoso para una operación tan común.Ejemplo:
Con esta respuesta, también quiero demostrar cuán simple es crear y usar recopiladores personalizados, lo cual es muy útil en general.
fuente
toList
si, por ejemplo, desea modificar la lista más adelante en el programa. LatoList
documentación dice esto: "No hay garantías sobre el tipo, mutabilidad, serialización o seguridad de subprocesos de la Lista devuelta; si se requiere más control sobre la Lista devuelta, úselatoCollection
". . Mi respuesta demuestra una forma de hacer que sea más conveniente hacerlo en un caso común.Si tiene una variedad de primitivas, puede usar las colecciones primitivas disponibles en Eclipse Collections .
Si no puede cambiar la fuenteLongList de
List
:Si quieres usar
LongStream
:Nota: Soy colaborador de Eclipse Collections.
fuente
Una forma un poco más eficiente (evite la creación de la Lista fuente y el desempaquetado automático por el filtro):
fuente
Esta es la llamada que puede usar para convertir cualquier Stream a List.
Más concretamente:
desde:
https://www.geeksforgeeks.org/collectors-tolist-method-in-java-with-examples/
fuente
Si no le importa usar bibliotecas de terceros, la biblioteca cyclops-react lib de AOL (revelación de que soy colaborador) tiene extensiones para todos los tipos de Colección JDK , incluida la Lista . La interfaz ListX extiende java.util.List y agrega una gran cantidad de operadores útiles, incluido el filtro.
Puedes simplemente escribir
ListX también se puede crear a partir de una lista existente (a través de ListX.fromIterable)
fuente
Existe otra variante del método de recopilación proporcionada por la clase LongStream y, de manera similar, también por las clases IntStream y DoubleStream.
Realiza una operación de reducción mutable en los elementos de esta secuencia. Una reducción mutable es aquella en la que el valor reducido es un contenedor de resultados mutables, como un ArrayList, y los elementos se incorporan actualizando el estado del resultado en lugar de reemplazarlo. Esto produce un resultado equivalente a:
Al igual que reduce (long, LongBinaryOperator), las operaciones de recopilación pueden paralelizarse sin requerir sincronización adicional. Esta es una operación terminal.
Y la respuesta a su pregunta con este método de recopilación es la siguiente:
A continuación se muestra la variante de referencia del método, que es bastante inteligente pero algo difícil de entender:
A continuación se mostrará la variante HashSet:
De manera similar, la variante LinkedList es así:
fuente
En caso de que alguien (como yo) esté buscando formas de tratar con Objetos en lugar de tipos primitivos, use
mapToObj()
huellas dactilares:
fuente
fuente
Aquí está el código de AbacusUtil
Divulgación: Soy el desarrollador de AbacusUtil.
fuente
com.landawn.abacus.util.stream.LongStream
oLongStreamEx
en AbacusUtilPuede reescribir el código de la siguiente manera:
fuente
Para recopilar en una lista mutable:
Para recopilar en una lista inmutable:
Explicación de
collect
desde el JavaDoc :fuente
Si no usas
parallel()
esto funcionaráfuente
collect
y luego no guardar el valor de retorno. En ese caso, podría usarforEach
en su lugar. Pero esa sigue siendo una mala solución.