Comprimir transmisiones usando JDK8 con lambda (java.util.stream.Streams.zip)
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. Streams
De 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).
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);
}
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"));
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) {
...
}
}
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);
}