DulcetAirman

Java 8 ZipperSpliterator from beta

Apr 22nd, 2014
142
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // use any package you like!
  2. package ch.claude-martin.zip;
  3.  
  4. import java.util.Objects;
  5. import java.util.Spliterator;
  6. import java.util.function.BiFunction;
  7. import java.util.function.Consumer;
  8. import java.util.stream.Stream;
  9. import java.util.stream.StreamSupport;
  10.  
  11. /**
  12.  * This code is from an early build of Java 8 Beta.
  13.  *
  14.  * <p>
  15.  * This was removed later and no zip function exists in the final Java 8 release: <a
  16.  * href="http://hg.openjdk.java.net/lambda/lambda/jdk/rev/569088178418">changeset
  17.  * 8789:569088178418.</a>
  18.  * <p>
  19.  * <a href="http://stackoverflow.com/questions/17640754">Discussion on Stackoverflow.</a>
  20.  *
  21.  */
  22. public final class StreamZipper {
  23.   /** A very simple Pair that can be used to zip two streams.
  24.    *
  25.    *  @author Claude Martin */
  26.   public static final class Pair<A, B> {
  27.     /** First element. */
  28.     public final A first;
  29.     /** Second element. */
  30.     public final B second;
  31.  
  32.     public Pair(A first, B second) {
  33.       super();
  34.       this.first = first;
  35.       this.second = second;
  36.     }
  37.  
  38.     /**
  39.      * Scala-style getter for {@link #first}.
  40.      *
  41.      * @see #first
  42.      * @return the first element.
  43.      */
  44.     public A _1() {
  45.       return this.first;
  46.     }
  47.  
  48.     /**
  49.      * Scala-style getter for {@link #second}.
  50.      *
  51.      * @see #second
  52.      * @return the second element.
  53.      */
  54.     public B _2() {
  55.       return this.second;
  56.     }
  57.  
  58.     /**
  59.      * Applies the given function to both elements of this pair.
  60.      *
  61.      * @see #uncurry(BiFunction)
  62.      * @param <R>
  63.      *          return type.
  64.      * @param f
  65.      *          A function on two elements.
  66.      * @throws NullPointerException
  67.      *           if f is null
  68.      * @return The result of applying this pair to f.
  69.      */
  70.     public <R> R applyTo(final BiFunction<? super A, ? super B, R> f) {
  71.       return f.apply(this.first, this.second);
  72.     }
  73.  
  74.     @Override
  75.     public int hashCode() {
  76.       return Objects.hash(this.first, this.second);
  77.     }
  78.  
  79.     @Override
  80.     public boolean equals(Object obj) {
  81.       if (this == obj)
  82.         return true;
  83.       if (!(obj instanceof Pair))
  84.         return false;
  85.       final Pair<?, ?> other = (Pair<?, ?>) obj;
  86.       return Objects.equals(this.first, other.first) && Objects.equals(this.second, other.second);
  87.     }
  88.  
  89.     /**
  90.      * Creates an inverted pair.
  91.      * <p>
  92.      * <code>(a, b) &rarr; (b, a)</code>
  93.      *
  94.      * @return <code>new Pair&lt;&gt;(this.second, this.first)</code>
  95.      */
  96.     public Pair<B, A> swap() {
  97.       return new Pair<>(this.second, this.first);
  98.     }
  99.  
  100.     /**
  101.      * This Pair as an array so that first is on index 0 and second is on index 1.
  102.      *
  103.      * @return <code>new Object[] { this.first, this.second };</code>
  104.      */
  105.     public Object[] toArray() {
  106.       return new Object[] { this.first, this.second };
  107.     }
  108.  
  109.     /**
  110.      * Returns a string representation of this Pair.
  111.      *
  112.      * @return "Pair(<i>first</i>, <i>second</i>)"
  113.      */
  114.     @Override
  115.     public String toString() {
  116.       return "Pair(" + this.first + ", " + this.second + ")";
  117.     }
  118.   }
  119.  
  120.   public static <A, B, C> Stream<C> zip(Stream<? extends A> a, Stream<? extends B> b,
  121.       BiFunction<? super A, ? super B, ? extends C> zipper) {
  122.     Objects.requireNonNull(zipper);
  123.     @SuppressWarnings("unchecked")
  124.     Spliterator<A> as = (Spliterator<A>) Objects.requireNonNull(a).spliterator();
  125.     @SuppressWarnings("unchecked")
  126.     Spliterator<B> bs = (Spliterator<B>) Objects.requireNonNull(b).spliterator();
  127.     // Combining loses DISTINCT and SORTED characteristics and for other
  128.     // characteristics the combined stream has a characteristic if both
  129.     // streams to combine have the characteristic
  130.     int characteristics = as.characteristics() & bs.characteristics()
  131.         & ~(Spliterator.DISTINCT | Spliterator.SORTED);
  132.     long size = Math.min(as.estimateSize(), bs.estimateSize());
  133.     Spliterator<C> cs = new ZipperSpliterator<>(as, bs, zipper, size, characteristics);
  134.     return StreamSupport.stream(cs, a.isParallel() || b.isParallel());
  135.   }
  136.  
  137.   final static Object NONE = new Object();
  138.  
  139.   private static final class ZipperSpliterator<A, B, C> extends
  140.       java.util.Spliterators.AbstractSpliterator<C> implements Consumer<Object> {
  141.     final Spliterator<A> as;
  142.     final Spliterator<B> bs;
  143.     final BiFunction<? super A, ? super B, ? extends C> zipper;
  144.     Object a;
  145.     Object b;
  146.  
  147.     ZipperSpliterator(Spliterator<A> as, Spliterator<B> bs,
  148.         BiFunction<? super A, ? super B, ? extends C> zipper, long est,
  149.         int additionalCharacteristics) {
  150.       super(est, additionalCharacteristics);
  151.       this.as = as;
  152.       this.bs = bs;
  153.       this.zipper = zipper;
  154.       this.a = NONE;
  155.     }
  156.  
  157.     @Override
  158.     public void accept(Object aOrB) {
  159.       if (this.a == NONE) {
  160.         this.a = aOrB;
  161.       } else {
  162.         this.b = aOrB;
  163.       }
  164.     }
  165.  
  166.     @Override
  167.     @SuppressWarnings("unchecked")
  168.     public boolean tryAdvance(Consumer<? super C> action) {
  169.       if (this.as.tryAdvance(this) && this.bs.tryAdvance(this)) {
  170.         Object _a = this.a;
  171.         this.a = NONE;
  172.         action.accept(this.zipper.apply((A) _a, (B) this.b));
  173.         return true;
  174.       }
  175.       return false;
  176.     }
  177.   }
  178. }
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×