streams parallel funciones ejemplo collection available java java-8 java-stream chaining

parallel - Java 8 aplica la función a todos los elementos de Stream sin romper la cadena de stream



stream<> java (5)

¿Hay alguna manera en Java de aplicar una función a todos los elementos de un Stream sin romper la cadena de Stream ? Sé que puedo llamar a cada forEach , pero ese método devuelve un void , no un Stream .


Creo que estás buscando Stream.peek . Pero lea los documentos cuidadosamente, ya que fue diseñado principalmente como un método de depuración. De los documentos:

Este método existe principalmente para admitir la depuración, donde desea ver los elementos a medida que fluyen más allá de un cierto punto en una canalización

La acción pasada a peek debe ser no interferente .


Estás buscando la función map() Stream .

ejemplo:

List<String> strings = stream .map(Object::toString) .collect(ArrayList::new, ArrayList::add, ArrayList::addAll);


Hay (al menos) 3 formas. Por el bien del código de ejemplo, asumí que desea llamar a los métodos de consumo 2 método methodA y methodB :

A. Use peek() :

list.stream().peek(x -> methodA(x)).forEach(x -> methodB(x));

Aunque los documentos dicen que solo se usa para "depurar", funciona (y está en producción en este momento)

B. Usa map() para llamar a methodA, luego regresa el elemento a la secuencia:

list.stream().map(x -> {method1(x); return x;}).forEach(x -> methodB(x));

Este es probablemente el enfoque más "aceptable".

C. Haz dos cosas en el forEach() :

list.stream().forEach(x -> {method1(x); methodB(x);});

Este es el menos flexible y puede no ser adecuado para su necesidad.


La mejor opción que tienes es aplicar un mapa a tu flujo. que devuelve una secuencia que consiste en los resultados de aplicar la función dada a los elementos de esta secuencia, por ejemplo:

IntStream.rangeClosed(40, 70).limit(20).mapToObj(i -> (Integer) i).map(item->item+3).map(item->item*2)...

(Secuencia de elementos de tipo StreamItemABC)

Estamos aplicando varias modificaciones al flujo, pero de esta manera no podemos pasar ningún argumento al método de asignación, para solucionarlo:

private void applyMethod(ParameterX parX) { someStreamX().map(n -> methodX(n, parX))... } private StreamItemABC methodX (StreamItemABC item, ParameterX parX) { return notification; }


No está completamente seguro de lo que quiere decir al breaking the stream chain , pero cualquier operación en una Stream que devuelva una Stream no romperá ni consumirá su transmisión. Los flujos son consumidos por terminal operations y, como observó, forEach no devuelve un Stream<T> y, como tal, finaliza el stream, ejecutando todas las operaciones intermediate antes de forEach y forEach.

En el ejemplo que proporcionaste en los comentarios:

myStream.map(obj -> {obj.foo(); return obj;}

Realmente no se puede hacer esto con un trazador de líneas. Por supuesto, podría usar una referencia de método, pero entonces su Stream devuelto sería de un tipo diferente (asumiendo que foo devuelve un tipo):

myStream.map(Obj::foo) // this will turn into Stream<T>, where T is // the return type of foo, instead of Stream<Obj>

Además, la operación de su map es con stateful , lo que está muy desaconsejado. Su código se compilará e incluso podría funcionar como usted lo desee, pero luego podría fallar. map operaciones del map deben ser stateless .