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
.