example ejemplo collection collections lambda java-8 java-stream

collections - ejemplo - Recuperar una lista de un java.util.stream.Stream en Java 8



java stream map to list (11)

Estaba jugando con Java 8 lambdas para filtrar colecciones fácilmente. 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 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?


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.


De una manera un poco más eficiente (evite crear la Lista de origen y el auto-desempaquetado por el filtro):

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


En caso de que alguien (como yo) esté buscando formas de tratar los Objetos en lugar de los tipos primitivos, use 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<Character> 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


Lo que está haciendo puede ser la forma más sencilla, siempre que su transmisión se mantenga secuencial; de lo contrario, tendrá que llamar a secuencial () antes de 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 veloz si el flujo fuera paralelo. Incluso entonces, no logrará el efecto deseado, ya que forEach es explícitamente no determinista, incluso en una secuencia secuencial, el orden de procesamiento del elemento no está garantizado. Tendría que usar forEachOrdered para garantizar el orden 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

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


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

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

Ejemplo:

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

Con esta respuesta también quiero demostrar lo sencillo que es crear y usar recopiladores personalizados, lo cual es muy útil en general.


Otro enfoque es utilizar Collectors.toCollection :

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


Si no le importa usar bibliotecas de terceros, la biblioteca cyclops-react ciclops de AOL (divulgación, contribuyo) tiene extensiones para todos los tipos de colecciones JDK , incluida la List . La interfaz de ListX extiende java.util.List y agrega una gran cantidad de operadores útiles, incluido el filtro.

Simplemente puedes escribir-

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

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


Si no usa parallel() esto funcionará

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


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

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

Si no puedes cambiar el sourceLongList de la List :

List<Long> sourceLongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L); List<Long> 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 un colaborador de Eclipse Collections.


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


collect(Collectors.toList());

Esta es la llamada que puede utilizar para convertir cualquier secuencia en lista.