Comprimir transmisiones usando JDK8 con lambda (java.util.stream.Streams.zip)

Resuelto artella asked hace 11 años • 14 respuestas

En JDK 8 con lambda b93 había una clase java.util.stream.Streams.zip en b93 que podía usarse para comprimir secuencias (esto se ilustra en el tutorial Explorando Java8 Lambdas. Parte 1 de Dhananjay Nene ). Esta función :

Crea un Stream combinado diferido y secuencial cuyos elementos son el resultado de combinar los elementos de dos streams.

Sin embargo, en b98 esto ha desaparecido. StreamsDe hecho , ni siquiera se puede acceder a la clase en java.util.stream en b98 .

¿Se ha movido esta funcionalidad y, de ser así, cómo puedo comprimir transmisiones de manera concisa usando b98?

La aplicación que tengo en mente es esta implementación java de Shen , donde reemplacé la funcionalidad zip en el

  • static <T> boolean every(Collection<T> c1, Collection<T> c2, BiPredicate<T, T> pred)
  • static <T> T find(Collection<T> c1, Collection<T> c2, BiPredicate<T, T> pred)

funciones con código bastante detallado (que no utiliza la funcionalidad de b98).

artella avatar Jul 14 '13 22:07 artella
Aceptado

Yo también necesitaba esto, así que tomé el código fuente de b93 y lo puse en una clase "util". Tuve que modificarlo ligeramente para que funcione con la API actual.

Como referencia, aquí está el código de trabajo (tómelo bajo su propia responsabilidad...):

public static<A, B, C> Stream<C> zip(Stream<? extends A> a,
                                     Stream<? extends B> b,
                                     BiFunction<? super A, ? super B, ? extends C> zipper) {
    Objects.requireNonNull(zipper);
    Spliterator<? extends A> aSpliterator = Objects.requireNonNull(a).spliterator();
    Spliterator<? extends B> bSpliterator = Objects.requireNonNull(b).spliterator();

    // Zipping loses DISTINCT and SORTED characteristics
    int characteristics = aSpliterator.characteristics() & bSpliterator.characteristics() &
            ~(Spliterator.DISTINCT | Spliterator.SORTED);

    long zipSize = ((characteristics & Spliterator.SIZED) != 0)
            ? Math.min(aSpliterator.getExactSizeIfKnown(), bSpliterator.getExactSizeIfKnown())
            : -1;

    Iterator<A> aIterator = Spliterators.iterator(aSpliterator);
    Iterator<B> bIterator = Spliterators.iterator(bSpliterator);
    Iterator<C> cIterator = new Iterator<C>() {
        @Override
        public boolean hasNext() {
            return aIterator.hasNext() && bIterator.hasNext();
        }

        @Override
        public C next() {
            return zipper.apply(aIterator.next(), bIterator.next());
        }
    };

    Spliterator<C> split = Spliterators.spliterator(cIterator, zipSize, characteristics);
    return (a.isParallel() || b.isParallel())
           ? StreamSupport.stream(split, true)
           : StreamSupport.stream(split, false);
}
siki avatar May 07 '2014 21:05 siki

zip es una de las funciones proporcionadas por la biblioteca protonpack .

Stream<String> streamA = Stream.of("A", "B", "C");
Stream<String> streamB  = Stream.of("Apple", "Banana", "Carrot", "Doughnut");

List<String> zipped = StreamUtils.zip(streamA,
                                      streamB,
                                      (a, b) -> a + " is for " + b)
                                 .collect(Collectors.toList());

assertThat(zipped,
           contains("A is for Apple", "B is for Banana", "C is for Carrot"));
Dominic Fox avatar Sep 04 '2014 14:09 Dominic Fox

Si tiene Guava en su proyecto, puede usar el método Streams.zip (se agregó en Guava 21):

Devuelve una secuencia en la que cada elemento es el resultado de pasar el elemento correspondiente de cada secuenciaA y secuenciaB para funcionar. El flujo resultante sólo será tan largo como el más corto de los dos flujos de entrada; si una secuencia es más larga, se ignorarán sus elementos adicionales. El flujo resultante no se puede dividir de manera eficiente. Esto puede perjudicar el rendimiento paralelo.

 public class Streams {
     ...

     public static <A, B, R> Stream<R> zip(Stream<A> streamA,
             Stream<B> streamB, BiFunction<? super A, ? super B, R> function) {
         ...
     }
 }
ZhekaKozlov avatar Mar 28 '2017 01:03 ZhekaKozlov

Comprimir dos secuencias usando JDK8 con lambda ( gist ).

public static <A, B, C> Stream<C> zip(Stream<A> streamA, Stream<B> streamB, BiFunction<A, B, C> zipper) {
    final Iterator<A> iteratorA = streamA.iterator();
    final Iterator<B> iteratorB = streamB.iterator();
    final Iterator<C> iteratorC = new Iterator<C>() {
        @Override
        public boolean hasNext() {
            return iteratorA.hasNext() && iteratorB.hasNext();
        }

        @Override
        public C next() {
            return zipper.apply(iteratorA.next(), iteratorB.next());
        }
    };
    final boolean parallel = streamA.isParallel() || streamB.isParallel();
    return iteratorToFiniteStream(iteratorC, parallel);
}

public static <T> Stream<T> iteratorToFiniteStream(Iterator<T> iterator, boolean parallel) {
    final Iterable<T> iterable = () -> iterator;
    return StreamSupport.stream(iterable.spliterator(), parallel);
}
Karol Król avatar Sep 01 '2015 22:09 Karol Król