Recuperando una lista de java.util.stream.Stream en Java 8

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 statement. Aquí está mi enfoque más conciso hasta ahora:

List sourceLongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L); List 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 forma más concisa. Hubiera esperado que la clase Stream tenga métodos como toList() , toSet() , …

¿Hay alguna manera de que las variables targetLongList puedan ser asignadas directamente por la tercera línea?

Lo que está haciendo puede ser la forma más sencilla, siempre que su flujo se mantenga secuencial; de lo contrario, tendrá que hacer una llamada a forEach () antes para forEach .

[editar más tarde: la razón por la cual la llamada a la secuencia () es necesaria es que el código tal como está ( forEach(targetLongList::add) ) sería racy si la transmisión fuera paralela. Incluso entonces, no se logrará el efecto deseado, ya que para cada forEach es explícitamente no determinista, incluso en un flujo secuencial no se garantiza el orden del procesamiento del elemento. forEachOrdered usar forEachOrdered para garantizar el orden correcto. La intención de los diseñadores de Stream API es que utilizará el recostackdor en esta situación, como se indica a continuación.]

Una alternativa es

 targetLongList = sourceLongList.stream() .filter(l -> l > 100) .collect(Collectors.toList()); 

Otro enfoque es usar Collectors.toCollection :

 targetLongList = sourceLongList.stream(). filter(l -> l > 100). collect(Collectors.toCollection(ArrayList::new)); 

Me gusta utilizar un método util que devuelve un recostackdor para ArrayList cuando eso es lo que quiero.

Creo que la solución que usa Collectors.toCollection(ArrayList::new) es demasiado ruidosa para una operación tan común.

Ejemplo:

 ArrayList result = sourceLongList.stream() .filter(l -> l > 100) .collect(toArrayList()); public static  Collector> toArrayList() { return Collectors.toCollection(ArrayList::new); } 

Con esta respuesta también quiero demostrar cuán simple es crear y usar recostackdores personalizados, lo cual es muy útil en general.

Si tiene una matriz de elementos primitivos, puede usar las colecciones primitivas disponibles en Colecciones Eclipse .

 LongList sourceLongList = LongLists.mutable.of(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L); LongList targetLongList = sourceLongList.select(l -> l > 100); 

Si no puede cambiar sourceLongList de List :

 List sourceLongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L); List targetLongList = ListAdapter.adapt(sourceLongList).select(l -> l > 100, new ArrayList<>()); 

Si quieres usar LongStream :

 long[] sourceLongs = new long[]{1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L}; LongList targetList = LongStream.of(sourceLongs) .filter(l -> l > 100) .collect(LongArrayList::new, LongArrayList::add, LongArrayList::addAll); 

Nota: soy colaborador de las colecciones de Eclipse.

Una forma un poco más eficiente (evitar la creación de la lista fuente y el auto-unboxing por el filtro):

 List targetLongList = LongStream.of(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L) .filter(l -> l > 100) .boxed() .collect(Collectors.toList()); 
 collect(Collectors.toList()); 

Esta es la llamada que puede usar para convertir cualquier Stream a List.

Si no te importa utilizar bibliotecas de terceros, el cíclope-reac lib de AOL (la revelación soy colaborador) tiene extensiones para todos los tipos de colecciones JDK , incluida la lista . La interfaz ListX amplía java.util.List y agrega una gran cantidad de operadores útiles, incluido el filtro.

Simplemente puede escribir-

 ListX sourceLongList = ListX.of(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L); ListX targetLongList = sourceLongList.filter(l -> l > 100); 

ListX también se puede crear a partir de una lista existente (a través de ListX.fromIterable)

En caso de que alguien (como yo) busque formas de tratar con Objetos en lugar de tipos primitivos, entonces usa mapToObj()

 String ss = "An alternative way is to insert the following VM option before " + "the -vmargs option in the Eclipse shortcut properties(edit the " + "field Target inside the Shortcut tab):"; List ll = ss .chars() .mapToObj(c -> new Character((char) c)) .collect(Collectors.toList()); System.out.println("List type: " + ll.getClass()); System.out.println("Elem type: " + ll.get(0).getClass()); ll.stream().limit(50).forEach(System.out::print); 

huellas dactilares:

 List type: class java.util.ArrayList Elem type: class java.lang.Character An alternative way is to insert the following VM o 

Aquí está el código de AbacusUtil

 LongStream.of(1, 10, 50, 80, 100, 120, 133, 333).filter(e -> e > 100).toList(); 

Divulgación: soy el desarrollador de AbacusUtil.

 String joined = Stream.of(isRead?"read":"", isFlagged?"flagged":"", isActionRequired?"action":"", isHide?"hide":"") .filter(s -> s != null && !s.isEmpty()) .collect(Collectors.joining(",")); 

Si no usa parallel() esto funcionará

 List sourceLongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L); List targetLongList = new ArrayList(); sourceLongList.stream().peek(i->targetLongList.add(i)).collect(Collectors.toList());