Saltar al contenido

Agregar un elemento al final de una secuencia para cada elemento que ya está en la secuencia

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 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 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.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *