Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // use any package you like!
- package ch.claude-martin.zip;
- import java.util.Objects;
- import java.util.Spliterator;
- import java.util.function.BiFunction;
- import java.util.function.Consumer;
- import java.util.stream.Stream;
- import java.util.stream.StreamSupport;
- /**
- * This code is from an early build of Java 8 Beta.
- *
- * <p>
- * This was removed later and no zip function exists in the final Java 8 release: <a
- * href="http://hg.openjdk.java.net/lambda/lambda/jdk/rev/569088178418">changeset
- * 8789:569088178418.</a>
- * <p>
- * <a href="http://stackoverflow.com/questions/17640754">Discussion on Stackoverflow.</a>
- *
- */
- public final class StreamZipper {
- /** A very simple Pair that can be used to zip two streams.
- *
- * @author Claude Martin */
- public static final class Pair<A, B> {
- /** First element. */
- public final A first;
- /** Second element. */
- public final B second;
- public Pair(A first, B second) {
- super();
- this.first = first;
- this.second = second;
- }
- /**
- * Scala-style getter for {@link #first}.
- *
- * @see #first
- * @return the first element.
- */
- public A _1() {
- return this.first;
- }
- /**
- * Scala-style getter for {@link #second}.
- *
- * @see #second
- * @return the second element.
- */
- public B _2() {
- return this.second;
- }
- /**
- * Applies the given function to both elements of this pair.
- *
- * @see #uncurry(BiFunction)
- * @param <R>
- * return type.
- * @param f
- * A function on two elements.
- * @throws NullPointerException
- * if f is null
- * @return The result of applying this pair to f.
- */
- public <R> R applyTo(final BiFunction<? super A, ? super B, R> f) {
- return f.apply(this.first, this.second);
- }
- @Override
- public int hashCode() {
- return Objects.hash(this.first, this.second);
- }
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (!(obj instanceof Pair))
- return false;
- final Pair<?, ?> other = (Pair<?, ?>) obj;
- return Objects.equals(this.first, other.first) && Objects.equals(this.second, other.second);
- }
- /**
- * Creates an inverted pair.
- * <p>
- * <code>(a, b) → (b, a)</code>
- *
- * @return <code>new Pair<>(this.second, this.first)</code>
- */
- public Pair<B, A> swap() {
- return new Pair<>(this.second, this.first);
- }
- /**
- * This Pair as an array so that first is on index 0 and second is on index 1.
- *
- * @return <code>new Object[] { this.first, this.second };</code>
- */
- public Object[] toArray() {
- return new Object[] { this.first, this.second };
- }
- /**
- * Returns a string representation of this Pair.
- *
- * @return "Pair(<i>first</i>, <i>second</i>)"
- */
- @Override
- public String toString() {
- return "Pair(" + this.first + ", " + this.second + ")";
- }
- }
- 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);
- @SuppressWarnings("unchecked")
- Spliterator<A> as = (Spliterator<A>) Objects.requireNonNull(a).spliterator();
- @SuppressWarnings("unchecked")
- Spliterator<B> bs = (Spliterator<B>) Objects.requireNonNull(b).spliterator();
- // Combining loses DISTINCT and SORTED characteristics and for other
- // characteristics the combined stream has a characteristic if both
- // streams to combine have the characteristic
- int characteristics = as.characteristics() & bs.characteristics()
- & ~(Spliterator.DISTINCT | Spliterator.SORTED);
- long size = Math.min(as.estimateSize(), bs.estimateSize());
- Spliterator<C> cs = new ZipperSpliterator<>(as, bs, zipper, size, characteristics);
- return StreamSupport.stream(cs, a.isParallel() || b.isParallel());
- }
- final static Object NONE = new Object();
- private static final class ZipperSpliterator<A, B, C> extends
- java.util.Spliterators.AbstractSpliterator<C> implements Consumer<Object> {
- final Spliterator<A> as;
- final Spliterator<B> bs;
- final BiFunction<? super A, ? super B, ? extends C> zipper;
- Object a;
- Object b;
- ZipperSpliterator(Spliterator<A> as, Spliterator<B> bs,
- BiFunction<? super A, ? super B, ? extends C> zipper, long est,
- int additionalCharacteristics) {
- super(est, additionalCharacteristics);
- this.as = as;
- this.bs = bs;
- this.zipper = zipper;
- this.a = NONE;
- }
- @Override
- public void accept(Object aOrB) {
- if (this.a == NONE) {
- this.a = aOrB;
- } else {
- this.b = aOrB;
- }
- }
- @Override
- @SuppressWarnings("unchecked")
- public boolean tryAdvance(Consumer<? super C> action) {
- if (this.as.tryAdvance(this) && this.bs.tryAdvance(this)) {
- Object _a = this.a;
- this.a = NONE;
- action.accept(this.zipper.apply((A) _a, (B) this.b));
- return true;
- }
- return false;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement