Te recomendamos que revises esta solución en un entorno controlado antes de enviarlo a producción, saludos.
Solución:
No puedes abrir una botella de vino y luego pasar la botella a otra persona y pedirle que la abra. de nuevo.
Por lo tanto, creo que esto no es posible por la naturaleza de streams para hacer lo que pidas.
Tienes una cadena de “procesamiento” por flujo. no puedes tener dos.
Entonces, lo más cerca que podría estar trabajando desde “su origen”, como
Stream.concat(someList.stream(), someList.stream().map(f));
por ejemplo. Y, por supuesto, cuando no tenga esa lista, podría optar por:
List someList = ts.collect(Collectors.asList());
primero.
Puedes implementar un Spliterator
que envuelve su flujo de origen. Internamente, creará el elemento “duplicado” para cada uno procesado y luego cambiará a esos duplicados una vez que la fuente esté vacía:
public class Duplicates implements Spliterator
private Spliterator source;
private Consumer addDuplicate;
private Builder extrasStreamBuilder = Stream.builder();
private Spliterator extrasSpliterator;
private Duplicates(Stream source, UnaryOperator f)
this.addDuplicate = t -> extrasStreamBuilder.add(f.apply(t));
this.source = source.spliterator();
public static Stream of(Stream source, UnaryOperator f)
return StreamSupport.stream(new Duplicates<>(source, f), false);
@Override
public boolean tryAdvance(Consumer super T> action)
boolean advanced = false;
if (extrasSpliterator == null)
advanced = source.tryAdvance(addDuplicate.andThen(action));
if (!advanced)
if (extrasSpliterator == null)
extrasSpliterator = extrasStreamBuilder.build().spliterator();
advanced = extrasSpliterator.tryAdvance(action);
return advanced;
@Override
public void forEachRemaining(Consumer super T> action)
if (extrasSpliterator == null)
source.forEachRemaining(addDuplicate.andThen(action));
extrasSpliterator = extrasStreamBuilder.build().spliterator();
extrasSpliterator.forEachRemaining(action);
// other spliterator methods worked with default (Eclipse) implementation for the example below, but should probably delegate to source
public static void main(String[] args)
List input = Arrays.asList("1", "2", "3");
Stream wrapper = Duplicates.of(input.stream(), i -> i + "0");
wrapper.forEach(System.out::println);
// Output:
// 1
// 2
// 3
// 10
// 20
// 30
Puede depender de su caso de uso si esto es lo suficientemente eficiente en lo que respecta al consumo de memoria mientras mantiene el extras
en el generador de secuencias.
La ventaja sobre la recopilación y el mapeo antes de su procesamiento de transmisión real es que solo atraviesa la fuente una vez. Esto puede ser útil cuando la recuperación de los elementos lleva mucho tiempo o el orden de los elementos puede cambiar entre secuencias.
También puede encadenar primero algunas operaciones de transmisión a la fuente antes de duplicarlas, nuevamente sin tener que recopilar el resultado intermedio en una colección.
Cuando es solo para los elementos y no para el orden (primero los elementos originales, luego los modificados), podría usar flatMap:
Stream s = ...;
Stream result = s.flatMap(x -> Stream.of(x, f.apply(x));
result.forEach(System.out::println);
Si el orden es relevante, uno podría preguntarse por qué quiere usar secuencias, porque no se beneficiará de una evaluación perezosa…
Si entiendes que ha resultado de ayuda nuestro post, sería de mucha ayuda si lo compartes con otros entusiastas de la programación de esta manera contrubuyes a extender nuestra información.