Advertisement
DulcetAirman

Java 8 ZipperSpliterator from beta

Apr 22nd, 2014
463
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 5.22 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement