diff --git a/user/super/com/google/gwt/emul/java/util/Arrays.java b/user/super/com/google/gwt/emul/java/util/Arrays.java
index 72da442..4229fe6 100644
--- a/user/super/com/google/gwt/emul/java/util/Arrays.java
+++ b/user/super/com/google/gwt/emul/java/util/Arrays.java
@@ -35,6 +35,11 @@
 import java.util.function.IntUnaryOperator;
 import java.util.function.LongBinaryOperator;
 import java.util.function.UnaryOperator;
+import java.util.stream.DoubleStream;
+import java.util.stream.IntStream;
+import java.util.stream.LongStream;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
 
 import javaemul.internal.ArrayHelper;
 import javaemul.internal.LongCompareHolder;
@@ -1452,6 +1457,38 @@
         Spliterator.IMMUTABLE | Spliterator.ORDERED);
   }
 
+  public static DoubleStream stream(double[] array) {
+    return stream(array, 0, array.length);
+  }
+
+  public static DoubleStream stream(double[] array, int startInclusive, int endExclusive) {
+    return StreamSupport.doubleStream(spliterator(array, startInclusive, endExclusive), false);
+  }
+
+  public static IntStream stream(int[] array) {
+    return stream(array, 0, array.length);
+  }
+
+  public static IntStream stream(int[] array, int startInclusive, int endExclusive) {
+    return StreamSupport.intStream(spliterator(array, startInclusive, endExclusive), false);
+  }
+
+  public static LongStream stream(long[] array) {
+    return stream(array, 0, array.length);
+  }
+
+  public static LongStream stream(long[] array, int startInclusive, int endExclusive) {
+    return StreamSupport.longStream(spliterator(array, startInclusive, endExclusive), false);
+  }
+
+  public static <T> Stream<T> stream(T[] array) {
+    return stream(array, 0, array.length);
+  }
+
+  public static <T> Stream<T> stream(T[] array, int startInclusive, int endExclusive) {
+    return StreamSupport.stream(spliterator(array, startInclusive, endExclusive), false);
+  }
+
   public static String toString(boolean[] a) {
     if (a == null) {
       return "null";
diff --git a/user/super/com/google/gwt/emul/java/util/Collection.java b/user/super/com/google/gwt/emul/java/util/Collection.java
index 379be6d..d678e05 100644
--- a/user/super/com/google/gwt/emul/java/util/Collection.java
+++ b/user/super/com/google/gwt/emul/java/util/Collection.java
@@ -18,6 +18,8 @@
 import static javaemul.internal.InternalPreconditions.checkNotNull;
 
 import java.util.function.Predicate;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
 
 /**
  * General-purpose interface for storing collections of objects.
@@ -49,6 +51,11 @@
   @Override
   Iterator<E> iterator();
 
+  default Stream<E> parallelStream() {
+    // no parallelism in gwt
+    return stream();
+  }
+
   boolean remove(Object o);
 
   boolean removeAll(Collection<?> c);
@@ -74,6 +81,10 @@
     return Spliterators.spliterator(this, 0);
   }
 
+  default Stream<E> stream() {
+    return StreamSupport.stream(spliterator(), false);
+  }
+
   Object[] toArray();
 
   <T> T[] toArray(T[] a);
diff --git a/user/super/com/google/gwt/emul/java/util/stream/BaseStream.java b/user/super/com/google/gwt/emul/java/util/stream/BaseStream.java
new file mode 100644
index 0000000..3d08e80
--- /dev/null
+++ b/user/super/com/google/gwt/emul/java/util/stream/BaseStream.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package java.util.stream;
+
+import java.util.Iterator;
+import java.util.Spliterator;
+
+/**
+ * See <a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/BaseStream.html">
+ * the official Java API doc</a> for details.
+ *
+ * @param <T> the contents of the stream
+ * @param <S> the type of stream implementing this interface
+ */
+public interface BaseStream<T,S extends BaseStream<T,S>> extends AutoCloseable {
+  Iterator<T> iterator();
+
+  Spliterator<T> spliterator();
+
+  boolean isParallel();
+
+  S sequential();
+
+  S parallel();
+
+  S unordered();
+
+  S onClose(Runnable closeHandler);
+
+  void close();
+}
diff --git a/user/super/com/google/gwt/emul/java/util/stream/DoubleStream.java b/user/super/com/google/gwt/emul/java/util/stream/DoubleStream.java
new file mode 100644
index 0000000..492f621
--- /dev/null
+++ b/user/super/com/google/gwt/emul/java/util/stream/DoubleStream.java
@@ -0,0 +1,1028 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package java.util.stream;
+
+import static javaemul.internal.InternalPreconditions.checkCriticalState;
+import static javaemul.internal.InternalPreconditions.checkNotNull;
+import static javaemul.internal.InternalPreconditions.checkState;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.DoubleSummaryStatistics;
+import java.util.HashSet;
+import java.util.OptionalDouble;
+import java.util.PrimitiveIterator;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.function.DoubleBinaryOperator;
+import java.util.function.DoubleConsumer;
+import java.util.function.DoubleFunction;
+import java.util.function.DoublePredicate;
+import java.util.function.DoubleSupplier;
+import java.util.function.DoubleToIntFunction;
+import java.util.function.DoubleToLongFunction;
+import java.util.function.DoubleUnaryOperator;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+import java.util.function.ObjDoubleConsumer;
+import java.util.function.Supplier;
+
+/**
+ * See <a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/DoubleStream.html">
+ * the official Java API doc</a> for details.
+ */
+public interface DoubleStream extends BaseStream<Double,DoubleStream> {
+
+  /**
+   * Value holder for various stream operations.
+   */
+  static final class ValueConsumer implements DoubleConsumer {
+    double value;
+
+    @Override
+    public void accept(double value) {
+      this.value = value;
+    }
+  }
+
+  static DoubleStream.Builder builder() {
+    return new Builder() {
+      private double[] items = new double[0];
+
+      @Override
+      public void accept(double t) {
+        checkState(items != null, "Builder already built");
+        items[items.length] = t;
+      }
+
+      @Override
+      public DoubleStream build() {
+        checkCriticalState(items != null, "Builder already built");
+        DoubleStream stream = Arrays.stream(items);
+        items = null;
+        return stream;
+      }
+    };
+  }
+
+  static DoubleStream concat(DoubleStream a, DoubleStream b) {
+    // This is nearly the same as flatMap, but inlined, wrapped around a single spliterator of
+    // these two objects, and without close() called as the stream progresses. Instead, close is
+    // invoked as part of the resulting stream's own onClose, so that either can fail without
+    // affecting the other, and correctly collecting suppressed exceptions.
+
+    // TODO replace this flatMap-ish spliterator with one that directly combines the two root
+    // streams
+    Spliterator<? extends DoubleStream> spliteratorOfStreams =
+        Arrays.asList(a, b).spliterator();
+    DoubleStream result = new DoubleStreamSource(null, new Spliterators.AbstractDoubleSpliterator(
+        Long.MAX_VALUE,
+        0
+    ) {
+      DoubleStream nextStream;
+      Spliterator.OfDouble next;
+
+      @Override
+      public boolean tryAdvance(DoubleConsumer action) {
+        // look for a new spliterator
+        while (advanceToNextSpliterator()) {
+          // if we have one, try to read and use it
+          if (next.tryAdvance(action)) {
+            return true;
+          } else {
+            nextStream = null;
+            // failed, null it out so we can find another
+            next = null;
+          }
+        }
+        return false;
+      }
+
+      private boolean advanceToNextSpliterator() {
+        while (next == null) {
+          if (!spliteratorOfStreams.tryAdvance(n -> {
+            if (n != null) {
+              nextStream = n;
+              next = n.spliterator();
+            }
+          })) {
+            return false;
+          }
+        }
+        return true;
+      }
+    });
+
+    result.onClose(a::close);
+    result.onClose(b::close);
+
+    return result;
+  }
+
+  static DoubleStream empty() {
+    return new EmptyDoubleStreamSource(null);
+  }
+
+  static DoubleStream generate(DoubleSupplier s) {
+    return StreamSupport.doubleStream(new Spliterators.AbstractDoubleSpliterator(
+        Long.MAX_VALUE,
+        Spliterator.IMMUTABLE | Spliterator.ORDERED
+    ) {
+      @Override
+      public boolean tryAdvance(DoubleConsumer action) {
+        action.accept(s.getAsDouble());
+        return true;
+      }
+    }, false);
+  }
+
+  static DoubleStream iterate(double seed, DoubleUnaryOperator f) {
+    return StreamSupport.doubleStream(new Spliterators.AbstractDoubleSpliterator(
+        Long.MAX_VALUE,
+        Spliterator.IMMUTABLE | Spliterator.ORDERED
+    ) {
+      private double next = seed;
+
+      @Override
+      public boolean tryAdvance(DoubleConsumer action) {
+        action.accept(next);
+        next = f.applyAsDouble(next);
+        return true;
+      }
+    }, false);
+  }
+
+  static DoubleStream of(double... values) {
+    return Arrays.stream(values);
+  }
+
+  static DoubleStream of(double t) {
+    // TODO consider a splittable that returns only a single value
+    return of(new double[]{t});
+  }
+
+  /**
+   * See
+   * <a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/DoubleStream.Builder.html">
+   * the official Java API doc</a> for details.
+   */
+  public interface Builder extends DoubleConsumer {
+    @Override
+    void accept(double t);
+
+    default DoubleStream.Builder add(double t) {
+      accept(t);
+      return this;
+    }
+
+    DoubleStream build();
+  }
+
+  boolean allMatch(DoublePredicate predicate);
+
+  boolean anyMatch(DoublePredicate predicate);
+
+  OptionalDouble average();
+
+  Stream<Double> boxed();
+
+  <R> R collect(Supplier<R> supplier, ObjDoubleConsumer<R> accumulator, BiConsumer<R,R> combiner);
+
+  long count();
+
+  DoubleStream distinct();
+
+  DoubleStream filter(DoublePredicate predicate);
+
+  OptionalDouble findAny();
+
+  OptionalDouble findFirst();
+
+  DoubleStream flatMap(DoubleFunction<? extends DoubleStream> mapper);
+
+  void forEach(DoubleConsumer action);
+
+  void forEachOrdered(DoubleConsumer action);
+
+  PrimitiveIterator.OfDouble iterator();
+
+  DoubleStream limit(long maxSize);
+
+  DoubleStream map(DoubleUnaryOperator mapper);
+
+  IntStream mapToInt(DoubleToIntFunction mapper);
+
+  LongStream mapToLong(DoubleToLongFunction mapper);
+
+  <U> Stream<U> mapToObj(DoubleFunction<? extends U> mapper);
+
+  OptionalDouble max();
+
+  OptionalDouble min();
+
+  boolean noneMatch(DoublePredicate predicate);
+
+  DoubleStream parallel();
+
+  DoubleStream peek(DoubleConsumer action);
+
+  OptionalDouble reduce(DoubleBinaryOperator op);
+
+  double reduce(double identity, DoubleBinaryOperator op);
+
+  DoubleStream sequential();
+
+  DoubleStream skip(long n);
+
+  DoubleStream sorted();
+
+  Spliterator.OfDouble spliterator();
+
+  double sum();
+
+  DoubleSummaryStatistics summaryStatistics();
+
+  double[] toArray();
+
+  /**
+   * Represents an empty stream, doing nothing for all methods.
+   */
+  static class EmptyDoubleStreamSource extends TerminatableStream<EmptyDoubleStreamSource>
+      implements DoubleStream {
+    public EmptyDoubleStreamSource(TerminatableStream<?> previous) {
+      super(previous);
+    }
+
+    @Override
+    public DoubleStream filter(DoublePredicate predicate) {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public DoubleStream map(DoubleUnaryOperator mapper) {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public <U> Stream<U> mapToObj(DoubleFunction<? extends U> mapper) {
+      throwIfTerminated();
+      return new Stream.EmptyStreamSource<U>(this);
+    }
+
+    @Override
+    public IntStream mapToInt(DoubleToIntFunction mapper) {
+      throwIfTerminated();
+      return new IntStream.EmptyIntStreamSource(this);
+    }
+
+    @Override
+    public LongStream mapToLong(DoubleToLongFunction mapper) {
+      throwIfTerminated();
+      return new LongStream.EmptyLongStreamSource(this);
+    }
+
+    @Override
+    public DoubleStream flatMap(DoubleFunction<? extends DoubleStream> mapper) {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public DoubleStream distinct() {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public DoubleStream sorted() {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public DoubleStream peek(DoubleConsumer action) {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public DoubleStream limit(long maxSize) {
+      throwIfTerminated();
+      checkState(maxSize >= 0, "maxSize may not be negative");
+      return this;
+    }
+
+    @Override
+    public DoubleStream skip(long n) {
+      throwIfTerminated();
+      checkState(n >= 0, "n may not be negative");
+      return this;
+    }
+
+    @Override
+    public void forEach(DoubleConsumer action) {
+      terminate();
+      // do nothing
+    }
+
+    @Override
+    public void forEachOrdered(DoubleConsumer action) {
+      terminate();
+      // do nothing
+    }
+
+    @Override
+    public double[] toArray() {
+      terminate();
+      return new double[0];
+    }
+
+    @Override
+    public double reduce(double identity, DoubleBinaryOperator op) {
+      terminate();
+      return identity;
+    }
+
+    @Override
+    public OptionalDouble reduce(DoubleBinaryOperator op) {
+      terminate();
+      return OptionalDouble.empty();
+    }
+
+    @Override
+    public <R> R collect(Supplier<R> supplier,
+                         ObjDoubleConsumer<R> accumulator,
+                         BiConsumer<R, R> combiner) {
+      terminate();
+      return supplier.get();
+    }
+
+    @Override
+    public double sum() {
+      terminate();
+      return 0;
+    }
+
+    @Override
+    public OptionalDouble min() {
+      terminate();
+      return OptionalDouble.empty();
+    }
+
+    @Override
+    public OptionalDouble max() {
+      terminate();
+      return OptionalDouble.empty();
+    }
+
+    @Override
+    public long count() {
+      terminate();
+      return 0;
+    }
+
+    @Override
+    public OptionalDouble average() {
+      terminate();
+      return OptionalDouble.empty();
+    }
+
+    @Override
+    public DoubleSummaryStatistics summaryStatistics() {
+      terminate();
+      return new DoubleSummaryStatistics();
+    }
+
+    @Override
+    public boolean anyMatch(DoublePredicate predicate) {
+      terminate();
+      return false;
+    }
+
+    @Override
+    public boolean allMatch(DoublePredicate predicate) {
+      terminate();
+      return true;
+    }
+
+    @Override
+    public boolean noneMatch(DoublePredicate predicate) {
+      terminate();
+      return true;
+    }
+
+    @Override
+    public OptionalDouble findFirst() {
+      terminate();
+      return OptionalDouble.empty();
+    }
+
+    @Override
+    public OptionalDouble findAny() {
+      terminate();
+      return OptionalDouble.empty();
+    }
+
+    @Override
+    public Stream<Double> boxed() {
+      throwIfTerminated();
+      return new Stream.EmptyStreamSource<Double>(this);
+    }
+
+    @Override
+    public DoubleStream sequential() {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public DoubleStream parallel() {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public PrimitiveIterator.OfDouble iterator() {
+      return Spliterators.iterator(spliterator());
+    }
+
+    @Override
+    public Spliterator.OfDouble spliterator() {
+      terminate();
+      return Spliterators.emptyDoubleSpliterator();
+    }
+
+    @Override
+    public boolean isParallel() {
+      throwIfTerminated();
+      return false;
+    }
+
+    @Override
+    public DoubleStream unordered() {
+      throwIfTerminated();
+      return this;
+    }
+  }
+
+  /**
+   * Double to Int map spliterator.
+   */
+  static final class MapToIntSpliterator extends Spliterators.AbstractIntSpliterator {
+    private final DoubleToIntFunction map;
+    private final Spliterator.OfDouble original;
+
+    public MapToIntSpliterator(DoubleToIntFunction map, Spliterator.OfDouble original) {
+      super(
+          original.estimateSize(),
+          original.characteristics() & ~(Spliterator.SORTED | Spliterator.DISTINCT)
+      );
+      checkNotNull(map);
+      this.map = map;
+      this.original = original;
+    }
+
+    @Override
+    public boolean tryAdvance(final IntConsumer action) {
+      return original.tryAdvance((double u) -> action.accept(map.applyAsInt(u)));
+    }
+  }
+
+  /**
+   * Double to Object map spliterator.
+   * @param <T> the type of Object in the spliterator
+   */
+  static final class MapToObjSpliterator<T> extends Spliterators.AbstractSpliterator<T> {
+    private final DoubleFunction<? extends T> map;
+    private final Spliterator.OfDouble original;
+
+    public MapToObjSpliterator(DoubleFunction<? extends T> map, Spliterator.OfDouble original) {
+      super(
+          original.estimateSize(),
+          original.characteristics() & ~(Spliterator.SORTED | Spliterator.DISTINCT)
+      );
+      checkNotNull(map);
+      this.map = map;
+      this.original = original;
+    }
+
+    @Override
+    public boolean tryAdvance(final Consumer<? super T> action) {
+      return original.tryAdvance((double u) -> action.accept(map.apply(u)));
+    }
+  }
+
+  /**
+   * Double to Long map spliterator.
+   */
+  static final class MapToLongSpliterator extends Spliterators.AbstractLongSpliterator {
+    private final DoubleToLongFunction map;
+    private final Spliterator.OfDouble original;
+
+    public MapToLongSpliterator(DoubleToLongFunction map, Spliterator.OfDouble original) {
+      super(
+          original.estimateSize(),
+          original.characteristics() & ~(Spliterator.SORTED | Spliterator.DISTINCT)
+      );
+      checkNotNull(map);
+      this.map = map;
+      this.original = original;
+    }
+
+    @Override
+    public boolean tryAdvance(final LongConsumer action) {
+      return original.tryAdvance((double u) -> action.accept(map.applyAsLong(u)));
+    }
+  }
+
+  /**
+   * Double to Double map spliterator.
+   */
+  static final class MapToDoubleSpliterator extends Spliterators.AbstractDoubleSpliterator {
+    private final DoubleUnaryOperator map;
+    private final Spliterator.OfDouble original;
+
+    public MapToDoubleSpliterator(DoubleUnaryOperator map, Spliterator.OfDouble original) {
+      super(
+          original.estimateSize(),
+          original.characteristics() & ~(Spliterator.SORTED | Spliterator.DISTINCT)
+      );
+      checkNotNull(map);
+      this.map = map;
+      this.original = original;
+    }
+
+    @Override
+    public boolean tryAdvance(final DoubleConsumer action) {
+      return original.tryAdvance((double u) -> action.accept(map.applyAsDouble(u)));
+    }
+  }
+
+  /**
+   * Double filter spliterator.
+   */
+  static final class FilterSpliterator extends Spliterators.AbstractDoubleSpliterator {
+    private final DoublePredicate filter;
+    private final Spliterator.OfDouble original;
+
+    private boolean found;
+
+    public FilterSpliterator(DoublePredicate filter, Spliterator.OfDouble original) {
+      super(original.estimateSize(), original.characteristics() & ~Spliterator.SIZED);
+      checkNotNull(filter);
+      this.filter = filter;
+      this.original = original;
+    }
+
+    @Override
+    public Comparator<? super Double> getComparator() {
+      return original.getComparator();
+    }
+
+    @Override
+    public boolean tryAdvance(final DoubleConsumer action) {
+      found = false;
+      while (!found && original.tryAdvance((double item) -> {
+        if (filter.test(item)) {
+          found = true;
+          action.accept(item);
+        }
+      })) {
+        // do nothing, work is done in tryAdvance
+      }
+
+      return found;
+    }
+  }
+
+  /**
+   * Double skip spliterator.
+   */
+  static final class SkipSpliterator extends Spliterators.AbstractDoubleSpliterator {
+    private long skip;
+    private final Spliterator.OfDouble original;
+
+    public SkipSpliterator(long skip, Spliterator.OfDouble original) {
+      super(
+          original.hasCharacteristics(Spliterator.SIZED)
+              ? Math.max(0, original.estimateSize() - skip)
+              : Long.MAX_VALUE,
+          original.characteristics()
+      );
+      this.skip = skip;
+      this.original = original;
+    }
+
+    @Override
+    public Comparator<? super Double> getComparator() {
+      return original.getComparator();
+    }
+
+    @Override
+    public boolean tryAdvance(DoubleConsumer action) {
+      while (skip > 0) {
+        if (!original.tryAdvance((double ignore) -> { })) {
+          return false;
+        }
+        skip--;
+      }
+      return original.tryAdvance(action);
+    }
+  }
+
+  /**
+   * Double limit spliterator.
+   */
+  static final class LimitSpliterator extends Spliterators.AbstractDoubleSpliterator {
+    private final long limit;
+    private final Spliterator.OfDouble original;
+    private int position = 0;
+
+    public LimitSpliterator(long limit, Spliterator.OfDouble original) {
+      super(
+          original.hasCharacteristics(Spliterator.SIZED)
+              ? Math.min(original.estimateSize(), limit)
+              : Long.MAX_VALUE,
+          original.characteristics()
+      );
+      this.limit = limit;
+      this.original = original;
+    }
+
+    @Override
+    public Comparator<? super Double> getComparator() {
+      return original.getComparator();
+    }
+
+    @Override
+    public boolean tryAdvance(DoubleConsumer action) {
+      if (limit <= position) {
+        return false;
+      }
+      boolean result = original.tryAdvance(action);
+      position++;
+      return result;
+    }
+  }
+
+  /**
+   * Main implementation of DoubleStream, wrapping a single spliterator, and an optional parent
+   * stream.
+   */
+  static class DoubleStreamSource extends TerminatableStream<DoubleStreamSource>
+      implements DoubleStream {
+    private final Spliterator.OfDouble spliterator;
+
+    public DoubleStreamSource(TerminatableStream<?> previous, Spliterator.OfDouble spliterator) {
+      super(previous);
+      this.spliterator = spliterator;
+    }
+
+    // terminals
+
+    @Override
+    public void forEach(DoubleConsumer action) {
+      forEachOrdered(action);
+    }
+
+    @Override
+    public void forEachOrdered(DoubleConsumer action) {
+      terminate();
+      spliterator.forEachRemaining(action);
+    }
+
+    @Override
+    public double[] toArray() {
+      terminate();
+      double[] entries = new double[0];
+      // this is legal in js, since the array will be backed by a JS array
+      spliterator.forEachRemaining((double value) -> entries[entries.length] = value);
+
+      return entries;
+    }
+
+    @Override
+    public double reduce(double identity, DoubleBinaryOperator op) {
+      terminate();
+      ValueConsumer holder = new ValueConsumer();
+      holder.value = identity;
+      spliterator.forEachRemaining((double value) -> {
+        holder.accept(op.applyAsDouble(holder.value, value));
+      });
+      return holder.value;
+    }
+
+    @Override
+    public OptionalDouble reduce(DoubleBinaryOperator op) {
+      ValueConsumer holder = new ValueConsumer();
+      if (spliterator.tryAdvance(holder)) {
+        return OptionalDouble.of(reduce(holder.value, op));
+      }
+      terminate();
+      return OptionalDouble.empty();
+    }
+
+    @Override
+    public <R> R collect(Supplier<R> supplier,
+                         ObjDoubleConsumer<R> accumulator,
+                         BiConsumer<R, R> combiner) {
+      terminate();
+      final R acc = supplier.get();
+      spliterator.forEachRemaining((double value) -> accumulator.accept(acc, value));
+      return acc;
+    }
+
+    @Override
+    public double sum() {
+      return summaryStatistics().getSum();
+    }
+
+    @Override
+    public OptionalDouble min() {
+      terminate();
+      final ValueConsumer holder = new ValueConsumer();
+      if (spliterator.tryAdvance((double value) -> holder.value = value)) {
+        spliterator.forEachRemaining((double value) -> {
+          holder.value = Math.min(holder.value, value);
+        });
+        return OptionalDouble.of(holder.value);
+      }
+      return OptionalDouble.empty();
+    }
+
+    @Override
+    public OptionalDouble max() {
+      terminate();
+      final ValueConsumer holder = new ValueConsumer();
+      if (spliterator.tryAdvance((double value) -> holder.value = value)) {
+        spliterator.forEachRemaining((double value) -> {
+          holder.value = Math.max(holder.value, value);
+        });
+        return OptionalDouble.of(holder.value);
+      }
+      return OptionalDouble.empty();
+    }
+
+    @Override
+    public long count() {
+      terminate();
+      long count = 0;
+      while (spliterator.tryAdvance((double value) -> { })) {
+        count++;
+      }
+      return count;
+    }
+
+    @Override
+    public OptionalDouble average() {
+      DoubleSummaryStatistics stats = summaryStatistics();
+      if (stats.getCount() == 0) {
+        return OptionalDouble.empty();
+      }
+      return OptionalDouble.of(stats.getAverage());
+    }
+
+    @Override
+    public DoubleSummaryStatistics summaryStatistics() {
+      return collect(
+          DoubleSummaryStatistics::new,
+          // TODO switch to a lambda reference once #9340 is fixed
+          (doubleSummaryStatistics, value) -> doubleSummaryStatistics.accept(value),
+          DoubleSummaryStatistics::combine
+      );
+    }
+
+    @Override
+    public boolean anyMatch(DoublePredicate predicate) {
+      return filter(predicate).findFirst().isPresent();
+    }
+
+    @Override
+    public boolean allMatch(DoublePredicate predicate) {
+      return !anyMatch(predicate.negate());
+    }
+
+    @Override
+    public boolean noneMatch(DoublePredicate predicate) {
+      return !anyMatch(predicate);
+    }
+
+    @Override
+    public OptionalDouble findFirst() {
+      terminate();
+      ValueConsumer holder = new ValueConsumer();
+      if (spliterator.tryAdvance(holder)) {
+        return OptionalDouble.of(holder.value);
+      }
+      return OptionalDouble.empty();
+    }
+
+    @Override
+    public OptionalDouble findAny() {
+      return findFirst();
+    }
+
+    @Override
+    public PrimitiveIterator.OfDouble iterator() {
+      return Spliterators.iterator(spliterator());
+    }
+
+    @Override
+    public Spliterator.OfDouble spliterator() {
+      terminate();
+      return spliterator;
+    }
+
+    // end terminals
+
+    // intermediates
+
+    @Override
+    public DoubleStream filter(DoublePredicate predicate) {
+      throwIfTerminated();
+      return new DoubleStreamSource(this, new FilterSpliterator(predicate, spliterator));
+    }
+
+    @Override
+    public DoubleStream map(DoubleUnaryOperator mapper) {
+      throwIfTerminated();
+      return new DoubleStreamSource(this, new MapToDoubleSpliterator(mapper, spliterator));
+    }
+
+    @Override
+    public <U> Stream<U> mapToObj(DoubleFunction<? extends U> mapper) {
+      throwIfTerminated();
+      return new Stream.StreamSource(this, new MapToObjSpliterator<U>(mapper, spliterator));
+    }
+
+    @Override
+    public IntStream mapToInt(DoubleToIntFunction mapper) {
+      throwIfTerminated();
+      return new IntStream.IntStreamSource(this, new MapToIntSpliterator(mapper, spliterator));
+    }
+
+    @Override
+    public LongStream mapToLong(DoubleToLongFunction mapper) {
+      throwIfTerminated();
+      return new LongStream.LongStreamSource(this, new MapToLongSpliterator(mapper, spliterator));
+    }
+
+    @Override
+    public DoubleStream flatMap(DoubleFunction<? extends DoubleStream> mapper) {
+      throwIfTerminated();
+      final Spliterator<? extends DoubleStream> spliteratorOfStreams =
+          new MapToObjSpliterator<DoubleStream>(mapper, spliterator);
+      return new DoubleStreamSource(this, new Spliterators.AbstractDoubleSpliterator(
+          Long.MAX_VALUE,
+          0
+      ) {
+        DoubleStream nextStream;
+        Spliterator.OfDouble next;
+
+        @Override
+        public boolean tryAdvance(DoubleConsumer action) {
+          // look for a new spliterator
+          while (advanceToNextSpliterator()) {
+            // if we have one, try to read and use it
+            if (next.tryAdvance(action)) {
+              return true;
+            } else {
+              nextStream.close();
+              nextStream = null;
+              // failed, null it out so we can find another
+              next = null;
+            }
+          }
+          return false;
+        }
+
+        private boolean advanceToNextSpliterator() {
+          while (next == null) {
+            if (!spliteratorOfStreams.tryAdvance(n -> {
+              if (n != null) {
+                nextStream = n;
+                next = n.spliterator();
+              }
+            })) {
+              return false;
+            }
+          }
+          return true;
+        }
+      });
+    }
+
+    @Override
+    public DoubleStream distinct() {
+      throwIfTerminated();
+      HashSet<Double> seen = new HashSet<>();
+      return filter(seen::add);
+    }
+
+    @Override
+    public DoubleStream sorted() {
+      throwIfTerminated();
+      return new DoubleStreamSource(this, new Spliterators.AbstractDoubleSpliterator(
+          spliterator.estimateSize(),
+          spliterator.characteristics() | Spliterator.SORTED
+      ) {
+        Spliterator.OfDouble ordered = null;
+
+        @Override
+        public Comparator<? super Double> getComparator() {
+          return null;
+        }
+
+        @Override
+        public boolean tryAdvance(DoubleConsumer action) {
+          if (ordered == null) {
+            double[] list = new double[0];
+            spliterator.forEachRemaining((double item) -> list[list.length] = item);
+            Arrays.sort(list);
+            ordered = Spliterators.spliterator(list, characteristics());
+          }
+          return ordered.tryAdvance(action);
+        }
+      });
+    }
+
+    @Override
+    public DoubleStream peek(DoubleConsumer action) {
+      checkNotNull(action);
+      throwIfTerminated();
+      return new DoubleStreamSource(this, new Spliterators.AbstractDoubleSpliterator(
+          spliterator.estimateSize(),
+          spliterator.characteristics()
+      ) {
+        @Override
+        public boolean tryAdvance(final DoubleConsumer innerAction) {
+          return spliterator.tryAdvance(action.andThen(innerAction));
+        }
+      });
+    }
+
+    @Override
+    public DoubleStream limit(long maxSize) {
+      throwIfTerminated();
+      checkState(maxSize >= 0, "maxSize may not be negative");
+      return new DoubleStreamSource(this, new LimitSpliterator(maxSize, spliterator));
+    }
+
+    @Override
+    public DoubleStream skip(long n) {
+      throwIfTerminated();
+      checkState(n >= 0, "n may not be negative");
+      if (n == 0) {
+        return this;
+      }
+      return new DoubleStreamSource(this, new SkipSpliterator(n, spliterator));
+    }
+
+    @Override
+    public Stream<Double> boxed() {
+      return mapToObj(Double::valueOf);
+    }
+
+    @Override
+    public DoubleStream sequential() {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public DoubleStream parallel() {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public boolean isParallel() {
+      throwIfTerminated();
+      return false;
+    }
+
+    @Override
+    public DoubleStream unordered() {
+      throwIfTerminated();
+      return this;
+    }
+  }
+}
diff --git a/user/super/com/google/gwt/emul/java/util/stream/IntStream.java b/user/super/com/google/gwt/emul/java/util/stream/IntStream.java
new file mode 100644
index 0000000..8a0816e
--- /dev/null
+++ b/user/super/com/google/gwt/emul/java/util/stream/IntStream.java
@@ -0,0 +1,1081 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package java.util.stream;
+
+import static javaemul.internal.InternalPreconditions.checkCriticalState;
+import static javaemul.internal.InternalPreconditions.checkNotNull;
+import static javaemul.internal.InternalPreconditions.checkState;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.IntSummaryStatistics;
+import java.util.OptionalDouble;
+import java.util.OptionalInt;
+import java.util.PrimitiveIterator;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntBinaryOperator;
+import java.util.function.IntConsumer;
+import java.util.function.IntFunction;
+import java.util.function.IntPredicate;
+import java.util.function.IntSupplier;
+import java.util.function.IntToDoubleFunction;
+import java.util.function.IntToLongFunction;
+import java.util.function.IntUnaryOperator;
+import java.util.function.LongConsumer;
+import java.util.function.ObjIntConsumer;
+import java.util.function.Supplier;
+
+/**
+ * See <a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/IntStream.html">
+ * the official Java API doc</a> for details.
+ */
+public interface IntStream extends BaseStream<Integer,IntStream> {
+
+  /**
+   * Value holder for various stream operations.
+   */
+  static final class ValueConsumer implements IntConsumer {
+    int value;
+
+    @Override
+    public void accept(int value) {
+      this.value = value;
+    }
+  }
+
+  static IntStream.Builder builder() {
+    return new Builder() {
+      private int[] items = new int[0];
+
+      @Override
+      public void accept(int t) {
+        checkState(items != null, "Builder already built");
+        items[items.length] = t;
+      }
+
+      @Override
+      public IntStream build() {
+        checkCriticalState(items != null, "Builder already built");
+        IntStream stream = Arrays.stream(items);
+        items = null;
+        return stream;
+      }
+    };
+  }
+
+  static IntStream concat(IntStream a, IntStream b) {
+    // This is nearly the same as flatMap, but inlined, wrapped around a single spliterator of
+    // these two objects, and without close() called as the stream progresses. Instead, close is
+    // invoked as part of the resulting stream's own onClose, so that either can fail without
+    // affecting the other, and correctly collecting suppressed exceptions.
+
+    // TODO replace this flatMap-ish spliterator with one that directly combines the two root
+    // streams
+    Spliterator<? extends IntStream> spliteratorOfStreams =
+        Arrays.asList(a, b).spliterator();
+    IntStream result = new IntStreamSource(null, new Spliterators.AbstractIntSpliterator(Long
+        .MAX_VALUE, 0) {
+      IntStream nextStream;
+      Spliterator.OfInt next;
+
+      @Override
+      public boolean tryAdvance(IntConsumer action) {
+        // look for a new spliterator
+        while (advanceToNextSpliterator()) {
+          // if we have one, try to read and use it
+          if (next.tryAdvance(action)) {
+            return true;
+          } else {
+            nextStream = null;
+            // failed, null it out so we can find another
+            next = null;
+          }
+        }
+        return false;
+      }
+
+      private boolean advanceToNextSpliterator() {
+        while (next == null) {
+          if (!spliteratorOfStreams.tryAdvance(n -> {
+            if (n != null) {
+              nextStream = n;
+              next = n.spliterator();
+            }
+          })) {
+            return false;
+          }
+        }
+        return true;
+      }
+    });
+
+    result.onClose(a::close);
+    result.onClose(b::close);
+
+    return result;
+  }
+
+  static IntStream empty() {
+    return new EmptyIntStreamSource(null);
+  }
+
+  static IntStream generate(final IntSupplier s) {
+    return StreamSupport.intStream(new Spliterators.AbstractIntSpliterator(
+        Long.MAX_VALUE,
+        Spliterator.IMMUTABLE | Spliterator.ORDERED
+    ) {
+      @Override
+      public boolean tryAdvance(IntConsumer action) {
+        action.accept(s.getAsInt());
+        return true;
+      }
+    }, false);
+  }
+
+  static IntStream iterate(int seed, IntUnaryOperator f) {
+    return StreamSupport.intStream(new Spliterators.AbstractIntSpliterator(
+        Long.MAX_VALUE,
+        Spliterator.IMMUTABLE | Spliterator.ORDERED
+    ) {
+      private int next = seed;
+
+      @Override
+      public boolean tryAdvance(IntConsumer action) {
+        action.accept(next);
+        next = f.applyAsInt(next);
+        return true;
+      }
+    }, false);
+  }
+
+  static IntStream of(int... values) {
+    return Arrays.stream(values);
+  }
+
+  static IntStream of(int t) {
+    // TODO consider a splittable that returns only a single value
+    return of(new int[]{t});
+  }
+
+  static IntStream range(int startInclusive, int endExclusive) {
+    if (startInclusive >= endExclusive) {
+      return empty();
+    }
+    return rangeClosed(startInclusive, endExclusive - 1);
+  }
+
+  static IntStream rangeClosed(int startInclusive, int endInclusive) {
+    if (startInclusive > endInclusive) {
+      return empty();
+    }
+    int count = endInclusive - startInclusive + 1;
+
+    return StreamSupport.intStream(new Spliterators.AbstractIntSpliterator(
+        count,
+        Spliterator.IMMUTABLE | Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED
+            | Spliterator.SORTED | Spliterator.DISTINCT
+    ) {
+      private int next = startInclusive;
+
+      @Override
+      public Comparator<? super Integer> getComparator() {
+        return null;
+      }
+
+      @Override
+      public boolean tryAdvance(IntConsumer action) {
+        if (next <= endInclusive) {
+          action.accept(next++);
+          return true;
+        }
+        return false;
+      }
+    }, false);
+  }
+
+  /**
+   * See
+   * <a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/IntStream.Builder.html">
+   * the official Java API doc</a> for details.
+   */
+  public interface Builder extends IntConsumer {
+    @Override
+    void accept(int t);
+
+    default IntStream.Builder add(int t) {
+      accept(t);
+      return this;
+    }
+
+    IntStream build();
+  }
+
+  boolean allMatch(IntPredicate predicate);
+
+  boolean anyMatch(IntPredicate predicate);
+
+  DoubleStream asDoubleStream();
+
+  LongStream asLongStream();
+
+  OptionalDouble average();
+
+  Stream<Integer> boxed();
+
+  <R> R collect(Supplier<R> supplier, ObjIntConsumer<R> accumulator, BiConsumer<R,R> combiner);
+
+  long count();
+
+  IntStream distinct();
+
+  IntStream filter(IntPredicate predicate);
+
+  OptionalInt findAny();
+
+  OptionalInt findFirst();
+
+  IntStream flatMap(IntFunction<? extends IntStream> mapper);
+
+  void forEach(IntConsumer action);
+
+  void forEachOrdered(IntConsumer action);
+
+  PrimitiveIterator.OfInt iterator();
+
+  IntStream limit(long maxSize);
+
+  IntStream map(IntUnaryOperator mapper);
+
+  DoubleStream mapToDouble(IntToDoubleFunction mapper);
+
+  LongStream mapToLong(IntToLongFunction mapper);
+
+  <U> Stream<U> mapToObj(IntFunction<? extends U> mapper);
+
+  OptionalInt max();
+
+  OptionalInt min();
+
+  boolean noneMatch(IntPredicate predicate);
+
+  IntStream parallel();
+
+  IntStream peek(IntConsumer action);
+
+  OptionalInt reduce(IntBinaryOperator op);
+
+  int reduce(int identity, IntBinaryOperator op);
+
+  IntStream sequential();
+
+  IntStream skip(long n);
+
+  IntStream sorted();
+
+  Spliterator.OfInt spliterator();
+
+  int sum();
+
+  IntSummaryStatistics summaryStatistics();
+
+  int[] toArray();
+
+  /**
+   * Represents an empty stream, doing nothing for all methods.
+   */
+  static class EmptyIntStreamSource extends TerminatableStream<EmptyIntStreamSource>
+      implements IntStream {
+    public EmptyIntStreamSource(TerminatableStream<?> previous) {
+      super(previous);
+    }
+
+    @Override
+    public IntStream filter(IntPredicate predicate) {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public IntStream map(IntUnaryOperator mapper) {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public <U> Stream<U> mapToObj(IntFunction<? extends U> mapper) {
+      throwIfTerminated();
+      return new Stream.EmptyStreamSource<U>(this);
+    }
+
+    @Override
+    public LongStream mapToLong(IntToLongFunction mapper) {
+      throwIfTerminated();
+      return new LongStream.EmptyLongStreamSource(this);
+    }
+
+    @Override
+    public DoubleStream mapToDouble(IntToDoubleFunction mapper) {
+      throwIfTerminated();
+      return new DoubleStream.EmptyDoubleStreamSource(this);
+    }
+
+    @Override
+    public IntStream flatMap(IntFunction<? extends IntStream> mapper) {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public IntStream distinct() {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public IntStream sorted() {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public IntStream peek(IntConsumer action) {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public IntStream limit(long maxSize) {
+      throwIfTerminated();
+      checkState(maxSize >= 0, "maxSize may not be negative");
+      return this;
+    }
+
+    @Override
+    public IntStream skip(long n) {
+      throwIfTerminated();
+      checkState(n >= 0, "n may not be negative");
+      return this;
+    }
+
+    @Override
+    public void forEach(IntConsumer action) {
+      terminate();
+      // do nothing
+    }
+
+    @Override
+    public void forEachOrdered(IntConsumer action) {
+      terminate();
+      // do nothing
+    }
+
+    @Override
+    public int[] toArray() {
+      terminate();
+      return new int[0];
+    }
+
+    @Override
+    public int reduce(int identity, IntBinaryOperator op) {
+      terminate();
+      return identity;
+    }
+
+    @Override
+    public OptionalInt reduce(IntBinaryOperator op) {
+      terminate();
+      return OptionalInt.empty();
+    }
+
+    @Override
+    public <R> R collect(Supplier<R> supplier,
+                         ObjIntConsumer<R> accumulator,
+                         BiConsumer<R, R> combiner) {
+      terminate();
+      return supplier.get();
+    }
+
+    @Override
+    public int sum() {
+      terminate();
+      return 0;
+    }
+
+    @Override
+    public OptionalInt min() {
+      terminate();
+      return OptionalInt.empty();
+    }
+
+    @Override
+    public OptionalInt max() {
+      terminate();
+      return OptionalInt.empty();
+    }
+
+    @Override
+    public long count() {
+      terminate();
+      return 0;
+    }
+
+    @Override
+    public OptionalDouble average() {
+      terminate();
+      return OptionalDouble.empty();
+    }
+
+    @Override
+    public IntSummaryStatistics summaryStatistics() {
+      terminate();
+      return new IntSummaryStatistics();
+    }
+
+    @Override
+    public boolean anyMatch(IntPredicate predicate) {
+      terminate();
+      return false;
+    }
+
+    @Override
+    public boolean allMatch(IntPredicate predicate) {
+      terminate();
+      return true;
+    }
+
+    @Override
+    public boolean noneMatch(IntPredicate predicate) {
+      terminate();
+      return true;
+    }
+
+    @Override
+    public OptionalInt findFirst() {
+      terminate();
+      return OptionalInt.empty();
+    }
+
+    @Override
+    public OptionalInt findAny() {
+      terminate();
+      return OptionalInt.empty();
+    }
+
+    @Override
+    public LongStream asLongStream() {
+      throwIfTerminated();
+      return new LongStream.EmptyLongStreamSource(this);
+    }
+
+    @Override
+    public DoubleStream asDoubleStream() {
+      throwIfTerminated();
+      return new DoubleStream.EmptyDoubleStreamSource(this);
+    }
+
+    @Override
+    public Stream<Integer> boxed() {
+      throwIfTerminated();
+      return new Stream.EmptyStreamSource<Integer>(this);
+    }
+
+    @Override
+    public IntStream sequential() {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public IntStream parallel() {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public PrimitiveIterator.OfInt iterator() {
+      return Spliterators.iterator(spliterator());
+    }
+
+    @Override
+    public Spliterator.OfInt spliterator() {
+      terminate();
+      return Spliterators.emptyIntSpliterator();
+    }
+
+    @Override
+    public boolean isParallel() {
+      throwIfTerminated();
+      return false;
+    }
+
+    @Override
+    public IntStream unordered() {
+      throwIfTerminated();
+      return this;
+    }
+  }
+
+  /**
+   * Int to Int map spliterator.
+   */
+  static final class MapToIntSpliterator extends Spliterators.AbstractIntSpliterator {
+    private final IntUnaryOperator map;
+    private final Spliterator.OfInt original;
+
+    public MapToIntSpliterator(IntUnaryOperator map, Spliterator.OfInt original) {
+      super(
+          original.estimateSize(),
+          original.characteristics() & ~(Spliterator.SORTED | Spliterator.DISTINCT)
+      );
+      checkNotNull(map);
+      this.map = map;
+      this.original = original;
+    }
+
+    @Override
+    public boolean tryAdvance(final IntConsumer action) {
+      return original.tryAdvance((int u) -> action.accept(map.applyAsInt(u)));
+    }
+  }
+
+  /**
+   * Int to Object map spliterator.
+   * @param <T> the type of data in the object spliterator
+   */
+  static final class MapToObjSpliterator<T> extends Spliterators.AbstractSpliterator<T> {
+    private final IntFunction<? extends T> map;
+    private final Spliterator.OfInt original;
+
+    public MapToObjSpliterator(IntFunction<? extends T> map, Spliterator.OfInt original) {
+      super(
+          original.estimateSize(),
+          original.characteristics() & ~(Spliterator.SORTED | Spliterator.DISTINCT)
+      );
+      checkNotNull(map);
+      this.map = map;
+      this.original = original;
+    }
+
+    @Override
+    public boolean tryAdvance(final Consumer<? super T> action) {
+      return original.tryAdvance((int u) -> action.accept(map.apply(u)));
+    }
+  }
+
+  /**
+   * Int to Long map spliterator.
+   */
+  static final class MapToLongSpliterator extends Spliterators.AbstractLongSpliterator {
+    private final IntToLongFunction map;
+    private final Spliterator.OfInt original;
+
+    public MapToLongSpliterator(IntToLongFunction map, Spliterator.OfInt original) {
+      super(
+          original.estimateSize(),
+          original.characteristics() & ~(Spliterator.SORTED | Spliterator.DISTINCT)
+      );
+      checkNotNull(map);
+      this.map = map;
+      this.original = original;
+    }
+
+    @Override
+    public boolean tryAdvance(final LongConsumer action) {
+      return original.tryAdvance((int u) -> action.accept(map.applyAsLong(u)));
+    }
+  }
+
+  /**
+   * Int to Double map spliterator.
+   */
+  static final class MapToDoubleSpliterator extends Spliterators.AbstractDoubleSpliterator {
+    private final IntToDoubleFunction map;
+    private final Spliterator.OfInt original;
+
+    public MapToDoubleSpliterator(IntToDoubleFunction map, Spliterator.OfInt original) {
+      super(
+          original.estimateSize(),
+          original.characteristics() & ~(Spliterator.SORTED | Spliterator.DISTINCT)
+      );
+      checkNotNull(map);
+      this.map = map;
+      this.original = original;
+    }
+
+    @Override
+    public boolean tryAdvance(final DoubleConsumer action) {
+      return original.tryAdvance((int u) -> action.accept(map.applyAsDouble(u)));
+    }
+  }
+
+  /**
+   * Int filter spliterator.
+   */
+  static final class FilterSpliterator extends Spliterators.AbstractIntSpliterator {
+    private final IntPredicate filter;
+    private final Spliterator.OfInt original;
+
+    private boolean found;
+
+    public FilterSpliterator(IntPredicate filter, Spliterator.OfInt original) {
+      super(original.estimateSize(), original.characteristics() & ~Spliterator.SIZED);
+      checkNotNull(filter);
+      this.filter = filter;
+      this.original = original;
+    }
+
+    @Override
+    public Comparator<? super Integer> getComparator() {
+      return original.getComparator();
+    }
+
+    @Override
+    public boolean tryAdvance(final IntConsumer action) {
+      found = false;
+      while (!found && original.tryAdvance((int item) -> {
+        if (filter.test(item)) {
+          found = true;
+          action.accept(item);
+        }
+      })) {
+        // do nothing, work is done in tryAdvance
+      }
+
+      return found;
+    }
+  }
+
+  /**
+   * Int skip spliterator.
+   */
+  static final class SkipSpliterator extends Spliterators.AbstractIntSpliterator {
+    private long skip;
+    private final Spliterator.OfInt original;
+
+    public SkipSpliterator(long skip, Spliterator.OfInt original) {
+      super(
+          original.hasCharacteristics(Spliterator.SIZED)
+              ? Math.max(0, original.estimateSize() - skip)
+              : Long.MAX_VALUE,
+          original.characteristics()
+      );
+      this.skip = skip;
+      this.original = original;
+    }
+
+    @Override
+    public Comparator<? super Integer> getComparator() {
+      return original.getComparator();
+    }
+
+    @Override
+    public boolean tryAdvance(IntConsumer action) {
+      while (skip > 0) {
+        if (!original.tryAdvance((int ignore) -> { })) {
+          return false;
+        }
+        skip--;
+      }
+      return original.tryAdvance(action);
+    }
+  }
+
+  /**
+   * Int limit spliterator.
+   */
+  static final class LimitSpliterator extends Spliterators.AbstractIntSpliterator {
+    private final long limit;
+    private final Spliterator.OfInt original;
+    private int position = 0;
+
+    public LimitSpliterator(long limit, Spliterator.OfInt original) {
+      super(
+          original.hasCharacteristics(Spliterator.SIZED)
+              ? Math.min(original.estimateSize(), limit)
+              : Long.MAX_VALUE,
+          original.characteristics()
+      );
+      this.limit = limit;
+      this.original = original;
+    }
+
+    @Override
+    public Comparator<? super Integer> getComparator() {
+      return original.getComparator();
+    }
+
+    @Override
+    public boolean tryAdvance(IntConsumer action) {
+      if (limit <= position) {
+        return false;
+      }
+      boolean result = original.tryAdvance(action);
+      position++;
+      return result;
+    }
+  }
+
+  /**
+   * Main implementation of IntStream, wrapping a single spliterator, and an optional parent stream.
+   */
+  static class IntStreamSource extends TerminatableStream<IntStreamSource> implements IntStream {
+    private final Spliterator.OfInt spliterator;
+
+    public IntStreamSource(TerminatableStream<?> previous, Spliterator.OfInt spliterator) {
+      super(previous);
+      this.spliterator = spliterator;
+    }
+
+    // terminals
+    @Override
+    public Spliterator.OfInt spliterator() {
+      terminate();
+      return spliterator;
+    }
+
+    @Override
+    public PrimitiveIterator.OfInt iterator() {
+      return Spliterators.iterator(spliterator());
+    }
+
+    @Override
+    public OptionalInt findFirst() {
+      terminate();
+      ValueConsumer holder = new ValueConsumer();
+      if (spliterator.tryAdvance(holder)) {
+        return OptionalInt.of(holder.value);
+      }
+      return OptionalInt.empty();
+    }
+
+    @Override
+    public OptionalInt findAny() {
+      return findFirst();
+    }
+
+    @Override
+    public boolean noneMatch(IntPredicate predicate) {
+      return !anyMatch(predicate);
+    }
+
+    @Override
+    public boolean allMatch(IntPredicate predicate) {
+      return !anyMatch(predicate.negate());
+    }
+
+    @Override
+    public boolean anyMatch(IntPredicate predicate) {
+      return filter(predicate).findFirst().isPresent();
+    }
+
+    @Override
+    public IntSummaryStatistics summaryStatistics() {
+      return collect(
+          IntSummaryStatistics::new,
+          // TODO switch to a lambda reference once #9340 is fixed
+          (intSummaryStatistics, value) -> intSummaryStatistics.accept(value),
+          IntSummaryStatistics::combine
+      );
+    }
+
+    @Override
+    public OptionalDouble average() {
+      IntSummaryStatistics stats = summaryStatistics();
+      if (stats.getCount() == 0) {
+        return OptionalDouble.empty();
+      }
+      return OptionalDouble.of(stats.getAverage());
+    }
+
+    @Override
+    public long count() {
+      terminate();
+      long count = 0;
+      while (spliterator.tryAdvance((int value) -> { })) {
+        count++;
+      }
+      return count;
+    }
+
+    @Override
+    public OptionalInt max() {
+      terminate();
+      final ValueConsumer holder = new ValueConsumer();
+      if (spliterator.tryAdvance((int value) -> holder.value = value)) {
+        spliterator.forEachRemaining((int value) -> holder.value = Math.max(holder.value, value));
+        return OptionalInt.of(holder.value);
+      }
+      return OptionalInt.empty();
+    }
+
+    @Override
+    public OptionalInt min() {
+      terminate();
+      final ValueConsumer holder = new ValueConsumer();
+      if (spliterator.tryAdvance((int value) -> holder.value = value)) {
+        spliterator.forEachRemaining((int value) -> holder.value = Math.min(holder.value, value));
+        return OptionalInt.of(holder.value);
+      }
+      return OptionalInt.empty();
+    }
+
+    @Override
+    public int sum() {
+      return (int) summaryStatistics().getSum();
+    }
+
+    @Override
+    public <R> R collect(Supplier<R> supplier,
+                         final ObjIntConsumer<R> accumulator,
+                         BiConsumer<R, R> combiner) {
+      terminate();
+      final R acc = supplier.get();
+      spliterator.forEachRemaining((int value) -> accumulator.accept(acc, value));
+      return acc;
+    }
+
+    @Override
+    public OptionalInt reduce(IntBinaryOperator op) {
+      ValueConsumer holder = new ValueConsumer();
+      if (spliterator.tryAdvance(holder)) {
+        return OptionalInt.of(reduce(holder.value, op));
+      }
+      terminate();
+      return OptionalInt.empty();
+    }
+
+    @Override
+    public int reduce(int identity, IntBinaryOperator op) {
+      terminate();
+      ValueConsumer holder = new ValueConsumer();
+      holder.value = identity;
+      spliterator.forEachRemaining((int value) -> {
+        holder.accept(op.applyAsInt(holder.value, value));
+      });
+      return holder.value;
+    }
+
+    @Override
+    public int[] toArray() {
+      terminate();
+      int[] entries = new int[0];
+      // this is legal in js, since the array will be backed by a JS array
+      spliterator.forEachRemaining((int value) -> entries[entries.length] = value);
+
+      return entries;
+    }
+
+    @Override
+    public void forEachOrdered(IntConsumer action) {
+      terminate();
+      spliterator.forEachRemaining(action);
+    }
+
+    @Override
+    public void forEach(IntConsumer action) {
+      forEachOrdered(action);
+    }
+    // end terminals
+
+    // intermediates
+
+    @Override
+    public IntStream filter(IntPredicate predicate) {
+      throwIfTerminated();
+      return new IntStreamSource(this, new FilterSpliterator(predicate, spliterator));
+    }
+
+    @Override
+    public IntStream map(IntUnaryOperator mapper) {
+      throwIfTerminated();
+      return new IntStreamSource(this, new MapToIntSpliterator(mapper, spliterator));
+    }
+
+    @Override
+    public <U> Stream<U> mapToObj(IntFunction<? extends U> mapper) {
+      throwIfTerminated();
+      return new Stream.StreamSource(this, new MapToObjSpliterator<U>(mapper, spliterator));
+    }
+
+    @Override
+    public LongStream mapToLong(IntToLongFunction mapper) {
+      throwIfTerminated();
+      return new LongStream.LongStreamSource(this, new MapToLongSpliterator(mapper, spliterator));
+    }
+
+    @Override
+    public DoubleStream mapToDouble(IntToDoubleFunction mapper) {
+      throwIfTerminated();
+      return new DoubleStream.DoubleStreamSource(
+          this,
+          new MapToDoubleSpliterator(mapper, spliterator)
+      );
+    }
+
+    @Override
+    public IntStream flatMap(IntFunction<? extends IntStream> mapper) {
+      throwIfTerminated();
+      final Spliterator<? extends IntStream> spliteratorOfStreams =
+          new MapToObjSpliterator<>(mapper, spliterator);
+      return new IntStreamSource(this, new Spliterators.AbstractIntSpliterator(Long.MAX_VALUE, 0) {
+        IntStream nextStream;
+        Spliterator.OfInt next;
+
+        @Override
+        public boolean tryAdvance(IntConsumer action) {
+          // look for a new spliterator
+          while (advanceToNextSpliterator()) {
+            // if we have one, try to read and use it
+            if (next.tryAdvance(action)) {
+              return true;
+            } else {
+              nextStream.close();
+              nextStream = null;
+              // failed, null it out so we can find another
+              next = null;
+            }
+          }
+          return false;
+        }
+
+        private boolean advanceToNextSpliterator() {
+          while (next == null) {
+            if (!spliteratorOfStreams.tryAdvance(n -> {
+              if (n != null) {
+                nextStream = n;
+                next = n.spliterator();
+              }
+            })) {
+              return false;
+            }
+          }
+          return true;
+        }
+      });
+    }
+
+    @Override
+    public IntStream distinct() {
+      throwIfTerminated();
+      HashSet<Integer> seen = new HashSet<>();
+      return filter(seen::add);
+    }
+
+    @Override
+    public IntStream sorted() {
+      throwIfTerminated();
+      return new IntStreamSource(this, new Spliterators.AbstractIntSpliterator(
+          spliterator.estimateSize(),
+          spliterator.characteristics() | Spliterator.SORTED
+      ) {
+        Spliterator.OfInt ordered = null;
+
+        @Override
+        public Comparator<? super Integer> getComparator() {
+          return null;
+        }
+
+        @Override
+        public boolean tryAdvance(IntConsumer action) {
+          if (ordered == null) {
+            int[] list = new int[0];
+            spliterator.forEachRemaining((int item) -> list[list.length] = item);
+            Arrays.sort(list);
+            ordered = Spliterators.spliterator(list, characteristics());
+          }
+          return ordered.tryAdvance(action);
+        }
+      });
+    }
+
+    @Override
+    public IntStream peek(IntConsumer action) {
+      checkNotNull(action);
+      throwIfTerminated();
+      return new IntStreamSource(this, new Spliterators.AbstractIntSpliterator(
+          spliterator.estimateSize(),
+          spliterator.characteristics()
+      ) {
+        @Override
+        public boolean tryAdvance(final IntConsumer innerAction) {
+          return spliterator.tryAdvance(action.andThen(innerAction));
+        }
+      });
+    }
+
+    @Override
+    public IntStream limit(long maxSize) {
+      throwIfTerminated();
+      checkState(maxSize >= 0, "maxSize may not be negative");
+      return new IntStreamSource(this, new LimitSpliterator(maxSize, spliterator));
+    }
+
+    @Override
+    public IntStream skip(long n) {
+      throwIfTerminated();
+      checkState(n >= 0, "n may not be negative");
+      if (n == 0) {
+        return this;
+      }
+      return new IntStreamSource(this, new SkipSpliterator(n, spliterator));
+    }
+
+    @Override
+    public LongStream asLongStream() {
+      return mapToLong(i -> (long) i);
+    }
+
+    @Override
+    public DoubleStream asDoubleStream() {
+      return mapToDouble(i -> (double) i);
+    }
+
+    @Override
+    public Stream<Integer> boxed() {
+      return mapToObj(Integer::valueOf);
+    }
+
+    @Override
+    public IntStream sequential() {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public IntStream parallel() {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public boolean isParallel() {
+      throwIfTerminated();
+      return false;
+    }
+
+    @Override
+    public IntStream unordered() {
+      throwIfTerminated();
+      return this;
+    }
+  }
+}
diff --git a/user/super/com/google/gwt/emul/java/util/stream/LongStream.java b/user/super/com/google/gwt/emul/java/util/stream/LongStream.java
new file mode 100644
index 0000000..f2b6ba1
--- /dev/null
+++ b/user/super/com/google/gwt/emul/java/util/stream/LongStream.java
@@ -0,0 +1,1072 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package java.util.stream;
+
+import static javaemul.internal.InternalPreconditions.checkCriticalState;
+import static javaemul.internal.InternalPreconditions.checkNotNull;
+import static javaemul.internal.InternalPreconditions.checkState;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.LongSummaryStatistics;
+import java.util.OptionalDouble;
+import java.util.OptionalLong;
+import java.util.PrimitiveIterator;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+import java.util.function.LongBinaryOperator;
+import java.util.function.LongConsumer;
+import java.util.function.LongFunction;
+import java.util.function.LongPredicate;
+import java.util.function.LongSupplier;
+import java.util.function.LongToDoubleFunction;
+import java.util.function.LongToIntFunction;
+import java.util.function.LongUnaryOperator;
+import java.util.function.ObjLongConsumer;
+import java.util.function.Supplier;
+
+/**
+ * See <a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/LongStream.html">
+ * the official Java API doc</a> for details.
+ */
+public interface LongStream extends BaseStream<Long,LongStream> {
+
+  /**
+   * Value holder for various stream operations.
+   */
+  static final class ValueConsumer implements LongConsumer {
+    long value;
+
+    @Override
+    public void accept(long value) {
+      this.value = value;
+    }
+  }
+
+  static LongStream.Builder builder() {
+    return new Builder() {
+      private long[] items = new long[0];
+
+      @Override
+      public void accept(long t) {
+        checkState(items != null, "Builder already built");
+        items[items.length] = t;
+      }
+
+      @Override
+      public LongStream build() {
+        checkCriticalState(items != null, "Builder already built");
+        LongStream stream = Arrays.stream(items);
+        items = null;
+        return stream;
+      }
+    };
+  }
+
+  static LongStream concat(LongStream a, LongStream b) {
+    // This is nearly the same as flatMap, but inlined, wrapped around a single spliterator of
+    // these two objects, and without close() called as the stream progresses. Instead, close is
+    // invoked as part of the resulting stream's own onClose, so that either can fail without
+    // affecting the other, and correctly collecting suppressed exceptions.
+
+    // TODO replace this flatMap-ish spliterator with one that directly combines the two root
+    // streams
+    Spliterator<? extends LongStream> spliteratorOfStreams =
+        Arrays.asList(a, b).spliterator();
+    LongStream result = new LongStreamSource(null, new Spliterators.AbstractLongSpliterator(Long
+        .MAX_VALUE, 0) {
+      LongStream nextStream;
+      Spliterator.OfLong next;
+
+      @Override
+      public boolean tryAdvance(LongConsumer action) {
+        // look for a new spliterator
+        while (advanceToNextSpliterator()) {
+          // if we have one, try to read and use it
+          if (next.tryAdvance(action)) {
+            return true;
+          } else {
+            nextStream = null;
+            // failed, null it out so we can find another
+            next = null;
+          }
+        }
+        return false;
+      }
+
+      private boolean advanceToNextSpliterator() {
+        while (next == null) {
+          if (!spliteratorOfStreams.tryAdvance(n -> {
+            if (n != null) {
+              nextStream = n;
+              next = n.spliterator();
+            }
+          })) {
+            return false;
+          }
+        }
+        return true;
+      }
+    });
+
+    result.onClose(a::close);
+    result.onClose(b::close);
+
+    return result;
+  }
+
+  static LongStream empty() {
+    return new EmptyLongStreamSource(null);
+  }
+
+  static LongStream generate(LongSupplier s) {
+    return StreamSupport.longStream(new Spliterators.AbstractLongSpliterator(
+        Long.MAX_VALUE,
+        Spliterator.IMMUTABLE | Spliterator.ORDERED
+    ) {
+      @Override
+      public boolean tryAdvance(LongConsumer action) {
+        action.accept(s.getAsLong());
+        return true;
+      }
+    }, false);
+  }
+
+  static LongStream iterate(long seed, LongUnaryOperator f) {
+    return StreamSupport.longStream(new Spliterators.AbstractLongSpliterator(
+        Long.MAX_VALUE,
+        Spliterator.IMMUTABLE | Spliterator.ORDERED
+    ) {
+      private long next = seed;
+
+      @Override
+      public boolean tryAdvance(LongConsumer action) {
+        action.accept(next);
+        next = f.applyAsLong(next);
+        return true;
+      }
+    }, false);
+  }
+
+  static LongStream of(long... values) {
+    return Arrays.stream(values);
+  }
+
+  static LongStream of(long t) {
+    // TODO consider a splittable that returns only a single value
+    return of(new long[]{t});
+  }
+
+  static LongStream range(long startInclusive, long endExclusive) {
+    if (startInclusive >= endExclusive) {
+      return empty();
+    }
+    return rangeClosed(startInclusive, endExclusive - 1);
+  }
+
+  static LongStream rangeClosed(long startInclusive, long endInclusive) {
+    if (startInclusive > endInclusive) {
+      return empty();
+    }
+    long count = endInclusive - startInclusive + 1;
+
+    return StreamSupport.longStream(new Spliterators.AbstractLongSpliterator(
+        count,
+        Spliterator.IMMUTABLE | Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.ORDERED
+            | Spliterator.SORTED | Spliterator.DISTINCT
+    ) {
+      private long next = startInclusive;
+
+      @Override
+      public Comparator<? super Long> getComparator() {
+        return null;
+      }
+
+      @Override
+      public boolean tryAdvance(LongConsumer action) {
+        if (next <= endInclusive) {
+          action.accept(next++);
+          return true;
+        }
+        return false;
+      }
+    }, false);
+  }
+
+  /**
+   * See
+   * <a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/LongStream.Builder.html">
+   * the official Java API doc</a> for details.
+   */
+  public interface Builder extends LongConsumer {
+    @Override
+    void accept(long t);
+
+    default LongStream.Builder add(long t) {
+      accept(t);
+      return this;
+    }
+
+    LongStream build();
+  }
+
+  boolean allMatch(LongPredicate predicate);
+
+  boolean anyMatch(LongPredicate predicate);
+
+  DoubleStream asDoubleStream();
+
+  OptionalDouble average();
+
+  Stream<Long> boxed();
+
+  <R> R collect(Supplier<R> supplier, ObjLongConsumer<R> accumulator, BiConsumer<R, R> combiner);
+
+  long count();
+
+  LongStream distinct();
+
+  LongStream filter(LongPredicate predicate);
+
+  OptionalLong findAny();
+
+  OptionalLong findFirst();
+
+  LongStream flatMap(LongFunction<? extends LongStream> mapper);
+
+  void forEach(LongConsumer action);
+
+  void forEachOrdered(LongConsumer action);
+
+  PrimitiveIterator.OfLong iterator();
+
+  LongStream limit(long maxSize);
+
+  LongStream map(LongUnaryOperator mapper);
+
+  DoubleStream mapToDouble(LongToDoubleFunction mapper);
+
+  IntStream mapToInt(LongToIntFunction mapper);
+
+  <U> Stream<U> mapToObj(LongFunction<? extends U> mapper);
+
+  OptionalLong max();
+
+  OptionalLong min();
+
+  boolean noneMatch(LongPredicate predicate);
+
+  LongStream parallel();
+
+  LongStream peek(LongConsumer action);
+
+  OptionalLong reduce(LongBinaryOperator op);
+
+  long reduce(long identity, LongBinaryOperator op);
+
+  LongStream sequential();
+
+  LongStream skip(long n);
+
+  LongStream sorted();
+
+  Spliterator.OfLong spliterator();
+
+  long sum();
+
+  LongSummaryStatistics summaryStatistics();
+
+  long[] toArray();
+
+  /**
+   * Represents an empty stream, doing nothing for all methods.
+   */
+  static class EmptyLongStreamSource extends TerminatableStream<EmptyLongStreamSource>
+      implements LongStream {
+    public EmptyLongStreamSource(TerminatableStream<?> previous) {
+      super(previous);
+    }
+
+    @Override
+    public LongStream filter(LongPredicate predicate) {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public LongStream map(LongUnaryOperator mapper) {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public <U> Stream<U> mapToObj(LongFunction<? extends U> mapper) {
+      throwIfTerminated();
+      return new Stream.EmptyStreamSource<U>(this);
+    }
+
+    @Override
+    public IntStream mapToInt(LongToIntFunction mapper) {
+      throwIfTerminated();
+      return new IntStream.EmptyIntStreamSource(this);
+    }
+
+    @Override
+    public DoubleStream mapToDouble(LongToDoubleFunction mapper) {
+      throwIfTerminated();
+      return new DoubleStream.EmptyDoubleStreamSource(this);
+    }
+
+    @Override
+    public LongStream flatMap(LongFunction<? extends LongStream> mapper) {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public LongStream distinct() {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public LongStream sorted() {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public LongStream peek(LongConsumer action) {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public LongStream limit(long maxSize) {
+      throwIfTerminated();
+      checkState(maxSize >= 0, "maxSize may not be negative");
+      return this;
+    }
+
+    @Override
+    public LongStream skip(long n) {
+      throwIfTerminated();
+      checkState(n >= 0, "n may not be negative");
+      return this;
+    }
+
+    @Override
+    public void forEach(LongConsumer action) {
+      terminate();
+    }
+
+    @Override
+    public void forEachOrdered(LongConsumer action) {
+      terminate();
+    }
+
+    @Override
+    public long[] toArray() {
+      terminate();
+      return new long[0];
+    }
+
+    @Override
+    public long reduce(long identity, LongBinaryOperator op) {
+      terminate();
+      return identity;
+    }
+
+    @Override
+    public OptionalLong reduce(LongBinaryOperator op) {
+      terminate();
+      return OptionalLong.empty();
+    }
+
+    @Override
+    public <R> R collect(Supplier<R> supplier,
+                         ObjLongConsumer<R> accumulator,
+                         BiConsumer<R, R> combiner) {
+      terminate();
+      return supplier.get();
+    }
+
+    @Override
+    public long sum() {
+      terminate();
+      return 0;
+    }
+
+    @Override
+    public OptionalLong min() {
+      terminate();
+      return OptionalLong.empty();
+    }
+
+    @Override
+    public OptionalLong max() {
+      terminate();
+      return OptionalLong.empty();
+    }
+
+    @Override
+    public long count() {
+      terminate();
+      return 0;
+    }
+
+    @Override
+    public OptionalDouble average() {
+      terminate();
+      return OptionalDouble.empty();
+    }
+
+    @Override
+    public LongSummaryStatistics summaryStatistics() {
+      terminate();
+      return new LongSummaryStatistics();
+    }
+
+    @Override
+    public boolean anyMatch(LongPredicate predicate) {
+      terminate();
+      return false;
+    }
+
+    @Override
+    public boolean allMatch(LongPredicate predicate) {
+      terminate();
+      return true;
+    }
+
+    @Override
+    public boolean noneMatch(LongPredicate predicate) {
+      terminate();
+      return true;
+    }
+
+    @Override
+    public OptionalLong findFirst() {
+      terminate();
+      return OptionalLong.empty();
+    }
+
+    @Override
+    public OptionalLong findAny() {
+      terminate();
+      return OptionalLong.empty();
+    }
+
+    @Override
+    public DoubleStream asDoubleStream() {
+      throwIfTerminated();
+      return new DoubleStream.EmptyDoubleStreamSource(this);
+    }
+
+    @Override
+    public Stream<Long> boxed() {
+      throwIfTerminated();
+      return new Stream.EmptyStreamSource<Long>(this);
+    }
+
+    @Override
+    public LongStream sequential() {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public LongStream parallel() {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public PrimitiveIterator.OfLong iterator() {
+      return Spliterators.iterator(spliterator());
+    }
+
+    @Override
+    public Spliterator.OfLong spliterator() {
+      terminate();
+      return Spliterators.emptyLongSpliterator();
+    }
+
+    @Override
+    public boolean isParallel() {
+      throwIfTerminated();
+      return false;
+    }
+
+    @Override
+    public LongStream unordered() {
+      throwIfTerminated();
+      return this;
+    }
+  }
+
+  /**
+   * Long to Int map spliterator.
+   */
+  static final class MapToIntSpliterator extends Spliterators.AbstractIntSpliterator {
+    private final LongToIntFunction map;
+    private final Spliterator.OfLong original;
+
+    public MapToIntSpliterator(LongToIntFunction map, Spliterator.OfLong original) {
+      super(
+          original.estimateSize(),
+          original.characteristics() & ~(Spliterator.SORTED | Spliterator.DISTINCT)
+      );
+      checkNotNull(map);
+      this.map = map;
+      this.original = original;
+    }
+
+    @Override
+    public boolean tryAdvance(final IntConsumer action) {
+      return original.tryAdvance((long u) -> action.accept(map.applyAsInt(u)));
+    }
+  }
+
+  /**
+   * Long to Object map spliterator.
+   * @param <T> the type of data in the object spliterator
+   */
+  static final class MapToObjSpliterator<T> extends Spliterators.AbstractSpliterator<T> {
+    private final LongFunction<? extends T> map;
+    private final Spliterator.OfLong original;
+
+    public MapToObjSpliterator(LongFunction<? extends T> map, Spliterator.OfLong original) {
+      super(
+          original.estimateSize(),
+          original.characteristics() & ~(Spliterator.SORTED | Spliterator.DISTINCT)
+      );
+      checkNotNull(map);
+      this.map = map;
+      this.original = original;
+    }
+
+    @Override
+    public boolean tryAdvance(final Consumer<? super T> action) {
+      return original.tryAdvance((long u) -> action.accept(map.apply(u)));
+    }
+  }
+
+  /**
+   * Long to Long map spliterator.
+   */
+  static final class MapToLongSpliterator extends Spliterators.AbstractLongSpliterator {
+    private final LongUnaryOperator map;
+    private final Spliterator.OfLong original;
+
+    public MapToLongSpliterator(LongUnaryOperator map, Spliterator.OfLong original) {
+      super(
+          original.estimateSize(),
+          original.characteristics() & ~(Spliterator.SORTED | Spliterator.DISTINCT)
+      );
+      checkNotNull(map);
+      this.map = map;
+      this.original = original;
+    }
+
+    @Override
+    public boolean tryAdvance(final LongConsumer action) {
+      return original.tryAdvance((long u) -> action.accept(map.applyAsLong(u)));
+    }
+  }
+
+  /**
+   * Long to Double map Spliterator.
+   */
+  static final class MapToDoubleSpliterator extends Spliterators.AbstractDoubleSpliterator {
+    private final LongToDoubleFunction map;
+    private final Spliterator.OfLong original;
+
+    public MapToDoubleSpliterator(LongToDoubleFunction map, Spliterator.OfLong original) {
+      super(
+          original.estimateSize(),
+          original.characteristics() & ~(Spliterator.SORTED | Spliterator.DISTINCT)
+      );
+      checkNotNull(map);
+      this.map = map;
+      this.original = original;
+    }
+
+    @Override
+    public boolean tryAdvance(final DoubleConsumer action) {
+      return original.tryAdvance((long u) -> action.accept(map.applyAsDouble(u)));
+    }
+  }
+
+  /**
+   * Long filter spliterator.
+   */
+  static final class FilterSpliterator extends Spliterators.AbstractLongSpliterator {
+    private final LongPredicate filter;
+    private final Spliterator.OfLong original;
+
+    private boolean found;
+
+    public FilterSpliterator(LongPredicate filter, Spliterator.OfLong original) {
+      super(original.estimateSize(), original.characteristics() & ~Spliterator.SIZED);
+      checkNotNull(filter);
+      this.filter = filter;
+      this.original = original;
+    }
+
+    @Override
+    public Comparator<? super Long> getComparator() {
+      return original.getComparator();
+    }
+
+    @Override
+    public boolean tryAdvance(final LongConsumer action) {
+      found = false;
+      while (!found && original.tryAdvance((long item) -> {
+        if (filter.test(item)) {
+          found = true;
+          action.accept(item);
+        }
+      })) {
+        // do nothing, work is done in tryAdvance
+      }
+
+      return found;
+    }
+  }
+
+  /**
+   * Long skip spliterator.
+   */
+  static final class SkipSpliterator extends Spliterators.AbstractLongSpliterator {
+    private long skip;
+    private final Spliterator.OfLong original;
+
+    public SkipSpliterator(long skip, Spliterator.OfLong original) {
+      super(
+          original.hasCharacteristics(Spliterator.SIZED)
+              ? Math.max(0, original.estimateSize() - skip)
+              : Long.MAX_VALUE,
+          original.characteristics()
+      );
+      this.skip = skip;
+      this.original = original;
+    }
+
+    @Override
+    public Comparator<? super Long> getComparator() {
+      return original.getComparator();
+    }
+
+    @Override
+    public boolean tryAdvance(LongConsumer action) {
+      while (skip > 0) {
+        if (!original.tryAdvance((long ignore) -> { })) {
+          return false;
+        }
+        skip--;
+      }
+      return original.tryAdvance(action);
+    }
+  }
+
+  /**
+   * Long limit spliterator.
+   */
+  static final class LimitSpliterator extends Spliterators.AbstractLongSpliterator {
+    private final long limit;
+    private final Spliterator.OfLong original;
+    private int position = 0;
+
+    public LimitSpliterator(long limit, Spliterator.OfLong original) {
+      super(
+          original.hasCharacteristics(Spliterator.SIZED)
+              ? Math.min(original.estimateSize(), limit)
+              : Long.MAX_VALUE,
+          original.characteristics()
+      );
+      this.limit = limit;
+      this.original = original;
+    }
+
+    @Override
+    public Comparator<? super Long> getComparator() {
+      return original.getComparator();
+    }
+
+    @Override
+    public boolean tryAdvance(LongConsumer action) {
+      if (limit <= position) {
+        return false;
+      }
+      boolean result = original.tryAdvance(action);
+      position++;
+      return result;
+    }
+  }
+
+  /**
+   * Main implementation of LongStream, wrapping a single spliterator, and an optional parent
+   * stream.
+   */
+  static class LongStreamSource extends TerminatableStream<LongStreamSource> implements LongStream {
+    private final Spliterator.OfLong spliterator;
+
+    public LongStreamSource(TerminatableStream<?> previous, Spliterator.OfLong spliterator) {
+      super(previous);
+      this.spliterator = spliterator;
+    }
+
+    // terminals
+
+    @Override
+    public void forEach(LongConsumer action) {
+      forEachOrdered(action);
+    }
+
+    @Override
+    public void forEachOrdered(LongConsumer action) {
+      terminate();
+      spliterator.forEachRemaining(action);
+    }
+
+    @Override
+    public long[] toArray() {
+      terminate();
+      long[] entries = new long[0];
+      // this is legal in js, since the array will be backed by a JS array
+      spliterator.forEachRemaining((long value) -> entries[entries.length] = value);
+
+      return entries;
+    }
+
+    @Override
+    public long reduce(long identity, LongBinaryOperator op) {
+      terminate();
+      ValueConsumer holder = new ValueConsumer();
+      holder.value = identity;
+      spliterator.forEachRemaining((long value) -> {
+        holder.accept(op.applyAsLong(holder.value, value));
+      });
+      return holder.value;
+    }
+
+    @Override
+    public OptionalLong reduce(LongBinaryOperator op) {
+      ValueConsumer holder = new ValueConsumer();
+      if (spliterator.tryAdvance(holder)) {
+        return OptionalLong.of(reduce(holder.value, op));
+      }
+      terminate();
+      return OptionalLong.empty();
+    }
+
+    @Override
+    public <R> R collect(Supplier<R> supplier,
+                         ObjLongConsumer<R> accumulator,
+                         BiConsumer<R, R> combiner) {
+      terminate();
+      final R acc = supplier.get();
+      spliterator.forEachRemaining((long value) -> accumulator.accept(acc, value));
+      return acc;
+    }
+
+    @Override
+    public long sum() {
+      return summaryStatistics().getSum();
+    }
+
+    @Override
+    public OptionalLong min() {
+      terminate();
+      final ValueConsumer holder = new ValueConsumer();
+      if (spliterator.tryAdvance((long value) -> holder.value = value)) {
+        spliterator.forEachRemaining((long value) -> holder.value = Math.min(holder.value, value));
+        return OptionalLong.of(holder.value);
+      }
+      return OptionalLong.empty();
+    }
+
+    @Override
+    public OptionalLong max() {
+      terminate();
+      final ValueConsumer holder = new ValueConsumer();
+      if (spliterator.tryAdvance((long value) -> holder.value = value)) {
+        spliterator.forEachRemaining((long value) -> holder.value = Math.max(holder.value, value));
+        return OptionalLong.of(holder.value);
+      }
+      return OptionalLong.empty();
+    }
+
+    @Override
+    public long count() {
+      terminate();
+      long count = 0;
+      while (spliterator.tryAdvance((long value) -> { })) {
+        count++;
+      }
+      return count;
+    }
+
+    @Override
+    public OptionalDouble average() {
+      LongSummaryStatistics stats = summaryStatistics();
+      if (stats.getCount() == 0) {
+        return OptionalDouble.empty();
+      }
+      return OptionalDouble.of(stats.getAverage());
+    }
+
+    @Override
+    public LongSummaryStatistics summaryStatistics() {
+      return collect(
+          LongSummaryStatistics::new,
+          // TODO switch to a lambda reference once #9340 is fixed
+          (longSummaryStatistics, value) -> longSummaryStatistics.accept(value),
+          LongSummaryStatistics::combine
+      );
+    }
+
+    @Override
+    public boolean anyMatch(LongPredicate predicate) {
+      return filter(predicate).findFirst().isPresent();
+    }
+
+    @Override
+    public boolean allMatch(LongPredicate predicate) {
+      return !anyMatch(predicate.negate());
+    }
+
+    @Override
+    public boolean noneMatch(LongPredicate predicate) {
+      return !anyMatch(predicate);
+    }
+
+    @Override
+    public OptionalLong findFirst() {
+      terminate();
+      ValueConsumer holder = new ValueConsumer();
+      if (spliterator.tryAdvance(holder)) {
+        return OptionalLong.of(holder.value);
+      }
+      return OptionalLong.empty();
+    }
+
+    @Override
+    public OptionalLong findAny() {
+      return findFirst();
+    }
+
+    @Override
+    public PrimitiveIterator.OfLong iterator() {
+      return Spliterators.iterator(spliterator());
+    }
+
+    @Override
+    public Spliterator.OfLong spliterator() {
+      terminate();
+      return spliterator;
+    }
+    // end terminals
+
+    // intermediates
+    @Override
+    public LongStream filter(LongPredicate predicate) {
+      throwIfTerminated();
+      return new LongStreamSource(this, new FilterSpliterator(predicate, spliterator));
+    }
+
+    @Override
+    public LongStream map(LongUnaryOperator mapper) {
+      throwIfTerminated();
+      return new LongStream.LongStreamSource(this, new MapToLongSpliterator(mapper, spliterator));
+    }
+
+    @Override
+    public <U> Stream<U> mapToObj(LongFunction<? extends U> mapper) {
+      throwIfTerminated();
+      return new Stream.StreamSource(this, new MapToObjSpliterator<U>(mapper, spliterator));
+    }
+
+    @Override
+    public IntStream mapToInt(LongToIntFunction mapper) {
+      throwIfTerminated();
+      return new IntStream.IntStreamSource(this, new MapToIntSpliterator(mapper, spliterator));
+    }
+
+    @Override
+    public DoubleStream mapToDouble(LongToDoubleFunction mapper) {
+      throwIfTerminated();
+      return new DoubleStream.DoubleStreamSource(this, new MapToDoubleSpliterator(
+          mapper,
+          spliterator)
+      );
+    }
+
+    @Override
+    public LongStream flatMap(LongFunction<? extends LongStream> mapper) {
+      throwIfTerminated();
+      final Spliterator<? extends LongStream> spliteratorOfStreams = new MapToObjSpliterator<>(
+          mapper,
+          spliterator
+      );
+      return new LongStreamSource(
+          this,
+          new Spliterators.AbstractLongSpliterator(Long.MAX_VALUE, 0
+          ) {
+            LongStream nextStream;
+            Spliterator.OfLong next;
+
+            @Override
+            public boolean tryAdvance(LongConsumer action) {
+              // look for a new spliterator
+              while (advanceToNextSpliterator()) {
+                // if we have one, try to read and use it
+                if (next.tryAdvance(action)) {
+                  return true;
+                } else {
+                  nextStream.close();
+                  nextStream = null;
+                  // failed, null it out so we can find another
+                  next = null;
+                }
+              }
+              return false;
+            }
+
+            private boolean advanceToNextSpliterator() {
+              while (next == null) {
+                if (!spliteratorOfStreams.tryAdvance(n -> {
+                  if (n != null) {
+                    nextStream = n;
+                    next = n.spliterator();
+                  }
+                })) {
+                  return false;
+                }
+              }
+              return true;
+            }
+          });
+    }
+
+    @Override
+    public LongStream distinct() {
+      throwIfTerminated();
+      HashSet<Long> seen = new HashSet<>();
+      return filter(seen::add);
+    }
+
+    @Override
+    public LongStream sorted() {
+      throwIfTerminated();
+      return new LongStreamSource(this, new Spliterators.AbstractLongSpliterator(
+          spliterator.estimateSize(),
+          spliterator.characteristics() | Spliterator.SORTED
+      ) {
+        Spliterator.OfLong ordered = null;
+
+        @Override
+        public Comparator<? super Long> getComparator() {
+          return null;
+        }
+
+        @Override
+        public boolean tryAdvance(LongConsumer action) {
+          if (ordered == null) {
+            long[] list = new long[0];
+            spliterator.forEachRemaining((long item) -> list[list.length] = item);
+            Arrays.sort(list);
+            ordered = Spliterators.spliterator(list, characteristics());
+          }
+          return ordered.tryAdvance(action);
+        }
+      });
+    }
+
+    @Override
+    public LongStream peek(LongConsumer action) {
+      checkNotNull(action);
+      throwIfTerminated();
+      return new LongStreamSource(this, new Spliterators.AbstractLongSpliterator(
+          spliterator.estimateSize(),
+          spliterator.characteristics()
+      ) {
+        @Override
+        public boolean tryAdvance(final LongConsumer innerAction) {
+          return spliterator.tryAdvance(action.andThen(innerAction));
+        }
+      });
+    }
+
+    @Override
+    public LongStream limit(long maxSize) {
+      throwIfTerminated();
+      checkState(maxSize >= 0, "maxSize may not be negative");
+      return new LongStreamSource(this, new LimitSpliterator(maxSize, spliterator));
+    }
+
+    @Override
+    public LongStream skip(long n) {
+      throwIfTerminated();
+      checkState(n >= 0, "n may not be negative");
+      if (n == 0) {
+        return this;
+      }
+      return new LongStreamSource(this, new SkipSpliterator(n, spliterator));
+    }
+
+    @Override
+    public DoubleStream asDoubleStream() {
+      return mapToDouble(x -> (double) x);
+    }
+
+    @Override
+    public Stream<Long> boxed() {
+      return mapToObj(Long::valueOf);
+    }
+
+    @Override
+    public LongStream sequential() {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public LongStream parallel() {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public boolean isParallel() {
+      throwIfTerminated();
+      return false;
+    }
+
+    @Override
+    public LongStream unordered() {
+      throwIfTerminated();
+      return this;
+    }
+  }
+}
diff --git a/user/super/com/google/gwt/emul/java/util/stream/Stream.java b/user/super/com/google/gwt/emul/java/util/stream/Stream.java
new file mode 100644
index 0000000..b61486d
--- /dev/null
+++ b/user/super/com/google/gwt/emul/java/util/stream/Stream.java
@@ -0,0 +1,1180 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package java.util.stream;
+
+import static javaemul.internal.InternalPreconditions.checkCriticalState;
+import static javaemul.internal.InternalPreconditions.checkNotNull;
+import static javaemul.internal.InternalPreconditions.checkState;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Optional;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.BinaryOperator;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.Function;
+import java.util.function.IntConsumer;
+import java.util.function.IntFunction;
+import java.util.function.LongConsumer;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.function.ToDoubleFunction;
+import java.util.function.ToIntFunction;
+import java.util.function.ToLongFunction;
+import java.util.function.UnaryOperator;
+
+/**
+ * See <a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html">
+ * the official Java API doc</a> for details.
+ *
+ * @param <T> the type of data being streamed
+ */
+public interface Stream<T> extends BaseStream<T, Stream<T>> {
+  /**
+   * Value holder for various stream operations.
+   */
+  static final class ValueConsumer<T> implements Consumer<T> {
+    T value;
+
+    @Override
+    public void accept(T value) {
+      this.value = value;
+    }
+  }
+
+  static <T> Stream.Builder<T> builder() {
+    return new Builder<T>() {
+      private Object[] items = new Object[0];
+
+      @Override
+      public void accept(T t) {
+        checkState(items != null, "Builder already built");
+        items[items.length] = t;
+      }
+
+      @Override
+      @SuppressWarnings("unchecked")
+      public Stream<T> build() {
+        checkCriticalState(items != null, "Builder already built");
+        Stream<T> stream = (Stream<T>) Arrays.stream(items);
+        items = null;
+        return stream;
+      }
+    };
+  }
+
+  static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) {
+    // This is nearly the same as flatMap, but inlined, wrapped around a single spliterator of
+    // these two objects, and without close() called as the stream progresses. Instead, close is
+    // invoked as part of the resulting stream's own onClose, so that either can fail without
+    // affecting the other, and correctly collecting suppressed exceptions.
+
+    // TODO replace this flatMap-ish spliterator with one that directly combines the two root
+    // streams
+    Spliterator<? extends Stream<? extends T>> spliteratorOfStreams =
+        Arrays.asList(a, b).spliterator();
+    Stream<T> result = new StreamSource<T>(null, new Spliterators.AbstractSpliterator<T>(Long
+        .MAX_VALUE, 0) {
+      Stream<? extends T> nextStream;
+      Spliterator<? extends T> next;
+
+      @Override
+      public boolean tryAdvance(Consumer<? super T> action) {
+        // look for a new spliterator
+        while (advanceToNextSpliterator()) {
+          // if we have one, try to read and use it
+          if (next.tryAdvance(action)) {
+            return true;
+          } else {
+            nextStream = null;
+            // failed, null it out so we can find another
+            next = null;
+          }
+        }
+        return false;
+      }
+
+      private boolean advanceToNextSpliterator() {
+        while (next == null) {
+          if (!spliteratorOfStreams.tryAdvance(n -> {
+            if (n != null) {
+              nextStream = n;
+              next = n.spliterator();
+            }
+          })) {
+            return false;
+          }
+        }
+        return true;
+      }
+    });
+
+    result.onClose(a::close);
+    result.onClose(b::close);
+
+    return result;
+  }
+
+  static <T> Stream<T> empty() {
+    return new EmptyStreamSource<T>(null);
+  }
+
+  static <T> Stream<T> generate(Supplier<T> s) {
+    return StreamSupport.stream(new Spliterators.AbstractSpliterator<T>(Long.MAX_VALUE,
+        Spliterator.IMMUTABLE | Spliterator.ORDERED) {
+      @Override
+      public boolean tryAdvance(Consumer<? super T> action) {
+        action.accept(s.get());
+        return true;
+      }
+    }, false);
+  }
+
+  static <T> Stream<T> iterate(T seed, UnaryOperator<T> f) {
+    return StreamSupport.stream(new Spliterators.AbstractSpliterator<T>(Long.MAX_VALUE,
+        Spliterator.IMMUTABLE | Spliterator.ORDERED) {
+      private T next = seed;
+
+      @Override
+      public boolean tryAdvance(Consumer<? super T> action) {
+        action.accept(next);
+        next = f.apply(next);
+        return true;
+      }
+    }, false);
+  }
+
+  static <T> Stream<T> of(T t) {
+    // TODO consider a splittable that returns only a single value, either for use here or in the
+    //      singleton collection types
+    return Collections.singleton(t).stream();
+  }
+
+  static <T> Stream<T> of(T... values) {
+    return Arrays.stream(values);
+  }
+
+  /**
+   * See <a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.Builder.html">
+   * the official Java API doc</a> for details.
+   */
+  public interface Builder<T> extends Consumer<T> {
+    @Override
+    void accept(T t);
+
+    default Stream.Builder<T> add(T t) {
+      accept(t);
+      return this;
+    }
+
+    Stream<T> build();
+  }
+
+  boolean allMatch(Predicate<? super T> predicate);
+
+  boolean anyMatch(Predicate<? super T> predicate);
+
+  <R,A> R collect(Collector<? super T,A,R> collector);
+
+  <R> R collect(Supplier<R> supplier,
+                BiConsumer<R,? super T> accumulator,
+                BiConsumer<R,R> combiner);
+
+  long count();
+
+  Stream<T> distinct();
+
+  Stream<T> filter(Predicate<? super T> predicate);
+
+  Optional<T> findAny();
+
+  Optional<T> findFirst();
+
+  <R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper);
+
+  DoubleStream flatMapToDouble(Function<? super T,? extends DoubleStream> mapper);
+
+  IntStream flatMapToInt(Function<? super T,? extends IntStream> mapper);
+
+  LongStream flatMapToLong(Function<? super T,? extends LongStream> mapper);
+
+  void forEach(Consumer<? super T> action);
+
+  void forEachOrdered(Consumer<? super T> action);
+
+  Stream<T> limit(long maxSize);
+
+  <R> Stream<R> map(Function<? super T,? extends R> mapper);
+
+  DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);
+
+  IntStream mapToInt(ToIntFunction<? super T> mapper);
+
+  LongStream mapToLong(ToLongFunction<? super T> mapper);
+
+  Optional<T> max(Comparator<? super T> comparator);
+
+  Optional<T> min(Comparator<? super T> comparator);
+
+  boolean noneMatch(Predicate<? super T> predicate);
+
+  Stream<T> peek(Consumer<? super T> action);
+
+  Optional<T> reduce(BinaryOperator<T> accumulator);
+
+  T reduce(T identity, BinaryOperator<T> accumulator);
+
+  <U> U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner);
+
+  Stream<T> skip(long n);
+
+  Stream<T> sorted();
+
+  Stream<T> sorted(Comparator<? super T> comparator);
+
+  Object[] toArray();
+
+  <A> A[] toArray(IntFunction<A[]> generator);
+
+  /**
+   * Represents an empty stream, doing nothing for all methods.
+   */
+  static class EmptyStreamSource<T> extends TerminatableStream<EmptyStreamSource<T>>
+      implements Stream<T> {
+
+    public EmptyStreamSource(TerminatableStream<?> previous) {
+      super(previous);
+    }
+
+    @Override
+    public  Stream<T> filter(Predicate<? super T> predicate) {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public <R>  Stream<R> map(Function<? super T, ? extends R> mapper) {
+      throwIfTerminated();
+      return (Stream) this;
+    }
+
+    @Override
+    public IntStream mapToInt(ToIntFunction<? super T> mapper) {
+      throwIfTerminated();
+      return new IntStream.EmptyIntStreamSource(this);
+    }
+
+    @Override
+    public LongStream mapToLong(ToLongFunction<? super T> mapper) {
+      throwIfTerminated();
+      return new LongStream.EmptyLongStreamSource(this);
+    }
+
+    @Override
+    public DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper) {
+      throwIfTerminated();
+      return new DoubleStream.EmptyDoubleStreamSource(this);
+    }
+
+    @Override
+    public <R> Stream<R> flatMap(Function<? super T, ? extends  Stream<? extends R>> mapper) {
+      throwIfTerminated();
+      return (Stream) this;
+    }
+
+    @Override
+    public IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper) {
+      throwIfTerminated();
+      return new IntStream.EmptyIntStreamSource(this);
+    }
+
+    @Override
+    public LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper) {
+      throwIfTerminated();
+      return new LongStream.EmptyLongStreamSource(this);
+    }
+
+    @Override
+    public DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper) {
+      throwIfTerminated();
+      return new DoubleStream.EmptyDoubleStreamSource(this);
+    }
+
+    @Override
+    public Stream<T> distinct() {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public Stream<T> sorted() {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public Stream<T> sorted(Comparator<? super T> comparator) {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public Stream<T> peek(Consumer<? super T> action) {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public Stream<T> limit(long maxSize) {
+      throwIfTerminated();
+      checkState(maxSize >= 0, "maxSize may not be negative");
+      return this;
+    }
+
+    @Override
+    public Stream<T> skip(long n) {
+      throwIfTerminated();
+      checkState(n >= 0, "n may not be negative");
+      return this;
+    }
+
+    @Override
+    public void forEach(Consumer<? super T> action) {
+      terminate();
+      // nothing to do
+    }
+
+    @Override
+    public void forEachOrdered(Consumer<? super T> action) {
+      terminate();
+      // nothing to do
+    }
+
+    @Override
+    public Object[] toArray() {
+      terminate();
+      return new Object[0];
+    }
+
+    @Override
+    public <A> A[] toArray(IntFunction<A[]> generator) {
+      terminate();
+      return generator.apply(0);
+    }
+
+    @Override
+    public T reduce(T identity, BinaryOperator<T> accumulator) {
+      terminate();
+      return identity;
+    }
+
+    @Override
+    public Optional<T> reduce(BinaryOperator<T> accumulator) {
+      terminate();
+      return Optional.empty();
+    }
+
+    @Override
+    public <U> U reduce(U identity,
+                        BiFunction<U, ? super T, U> accumulator,
+                        BinaryOperator<U> combiner) {
+      terminate();
+      return identity;
+    }
+
+    @Override
+    public <R> R collect(Supplier<R> supplier,
+                         BiConsumer<R, ? super T> accumulator,
+                         BiConsumer<R, R> combiner) {
+      terminate();
+      return supplier.get();
+    }
+
+    @Override
+    public <R, A> R collect(Collector<? super T, A, R> collector) {
+      terminate();
+      return collector.finisher().apply(collector.supplier().get());
+    }
+
+    @Override
+    public Optional<T> min(Comparator<? super T> comparator) {
+      terminate();
+      return Optional.empty();
+    }
+
+    @Override
+    public Optional<T> max(Comparator<? super T> comparator) {
+      terminate();
+      return Optional.empty();
+    }
+
+    @Override
+    public long count() {
+      terminate();
+      return 0;
+    }
+
+    @Override
+    public boolean anyMatch(Predicate<? super T> predicate) {
+      terminate();
+      return false;
+    }
+
+    @Override
+    public boolean allMatch(Predicate<? super T> predicate) {
+      terminate();
+      return true;
+    }
+
+    @Override
+    public boolean noneMatch(Predicate<? super T> predicate) {
+      terminate();
+      return true;
+    }
+
+    @Override
+    public Optional<T> findFirst() {
+      terminate();
+      return Optional.empty();
+    }
+
+    @Override
+    public Optional<T> findAny() {
+      terminate();
+      return Optional.empty();
+    }
+
+    @Override
+    public Iterator<T> iterator() {
+      terminate();
+      return Collections.emptyIterator();
+    }
+
+    @Override
+    public Spliterator<T> spliterator() {
+      terminate();
+      return Spliterators.emptySpliterator();
+    }
+
+    @Override
+    public boolean isParallel() {
+      throwIfTerminated();
+      return false;
+    }
+
+    @Override
+    public Stream<T> sequential() {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public Stream<T> parallel() {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public Stream<T> unordered() {
+      throwIfTerminated();
+      return this;
+    }
+  }
+
+  /**
+   * Object to Object map spliterator.
+   * @param <U> the input type
+   * @param <T> the output type
+   */
+  static final class MapToObjSpliterator<U, T> extends Spliterators.AbstractSpliterator<T> {
+    private final Function<? super U, ? extends T> map;
+    private final Spliterator<U> original;
+
+    public MapToObjSpliterator(Function<? super U, ? extends T> map, Spliterator<U> original) {
+      super(
+          original.estimateSize(),
+          original.characteristics() & ~(Spliterator.SORTED | Spliterator.DISTINCT)
+      );
+      checkNotNull(map);
+      this.map = map;
+      this.original = original;
+    }
+
+    @Override
+    public boolean tryAdvance(final Consumer<? super T> action) {
+      return original.tryAdvance(u -> action.accept(map.apply(u)));
+    }
+  }
+
+  /**
+   * Object to Int map spliterator.
+   * @param <T> the input type
+   */
+  static final class MapToIntSpliterator<T> extends Spliterators.AbstractIntSpliterator {
+    private final ToIntFunction<? super T> map;
+    private final Spliterator<T> original;
+
+    public MapToIntSpliterator(ToIntFunction<? super T> map, Spliterator<T> original) {
+      super(
+          original.estimateSize(),
+          original.characteristics() & ~(Spliterator.SORTED | Spliterator.DISTINCT)
+      );
+      checkNotNull(map);
+      this.map = map;
+      this.original = original;
+    }
+
+    @Override
+    public boolean tryAdvance(final IntConsumer action) {
+      return original.tryAdvance(u -> action.accept(map.applyAsInt(u)));
+    }
+  }
+
+  /**
+   * Object to Long map spliterator.
+   * @param <T> the input type
+   */
+  static final class MapToLongSpliterator<T> extends Spliterators.AbstractLongSpliterator {
+    private final ToLongFunction<? super T> map;
+    private final Spliterator<T> original;
+
+    public MapToLongSpliterator(ToLongFunction<? super T> map, Spliterator<T> original) {
+      super(
+          original.estimateSize(),
+          original.characteristics() & ~(Spliterator.SORTED | Spliterator.DISTINCT)
+      );
+      checkNotNull(map);
+      this.map = map;
+      this.original = original;
+    }
+
+    @Override
+    public boolean tryAdvance(final LongConsumer action) {
+      return original.tryAdvance(u -> action.accept(map.applyAsLong(u)));
+    }
+  }
+
+  /**
+   * Object to Double map spliterator.
+   * @param <T> the input type
+   */
+  static final class MapToDoubleSpliterator<T> extends Spliterators.AbstractDoubleSpliterator {
+    private final ToDoubleFunction<? super T> map;
+    private final Spliterator<T> original;
+
+    public MapToDoubleSpliterator(ToDoubleFunction<? super T> map, Spliterator<T> original) {
+      super(
+          original.estimateSize(),
+          original.characteristics() & ~(Spliterator.SORTED | Spliterator.DISTINCT)
+      );
+      checkNotNull(map);
+      this.map = map;
+      this.original = original;
+    }
+
+    @Override
+    public boolean tryAdvance(final DoubleConsumer action) {
+      return original.tryAdvance(u -> action.accept(map.applyAsDouble(u)));
+    }
+  }
+
+  /**
+   * Object filter spliterator.
+   * @param <T> the type of data to iterate over
+   */
+  static final class FilterSpliterator<T> extends Spliterators.AbstractSpliterator<T> {
+    private final Predicate<? super T> filter;
+    private final Spliterator<T> original;
+
+    private boolean found;
+
+    public FilterSpliterator(Predicate<? super T> filter, Spliterator<T> original) {
+      super(original.estimateSize(), original.characteristics() & ~Spliterator.SIZED);
+      checkNotNull(filter);
+      this.filter = filter;
+      this.original = original;
+    }
+
+    @Override
+    public Comparator<? super T> getComparator() {
+      return original.getComparator();
+    }
+
+    @Override
+    public boolean tryAdvance(final Consumer<? super T> action) {
+      found = false;
+      while (!found && original.tryAdvance(item -> {
+        if (filter.test(item)) {
+          found = true;
+          action.accept(item);
+        }
+      })) {
+        // do nothing, work is done in tryAdvance
+      }
+
+      return found;
+    }
+  }
+
+  /**
+   * Object skip spliterator.
+   * @param <T> the type of data to iterate over
+   */
+  static final class SkipSpliterator<T> extends Spliterators.AbstractSpliterator<T> {
+    private long skip;
+    private final Spliterator<T> original;
+
+    public SkipSpliterator(long skip, Spliterator<T> original) {
+      super(
+          original.hasCharacteristics(Spliterator.SIZED)
+              ? Math.max(0, original.estimateSize() - skip)
+              : Long.MAX_VALUE,
+          original.characteristics()
+      );
+      this.skip = skip;
+      this.original = original;
+    }
+
+    @Override
+    public Comparator<? super T> getComparator() {
+      return original.getComparator();
+    }
+
+    @Override
+    public boolean tryAdvance(Consumer<? super T> action) {
+      while (skip > 0) {
+        if (!original.tryAdvance(ignore -> { })) {
+          return false;
+        }
+        skip--;
+      }
+      return original.tryAdvance(action);
+    }
+  }
+
+  /**
+   * Object limit spliterator.
+   * @param <T> the type of data to iterate over
+   */
+  static final class LimitSpliterator<T> extends Spliterators.AbstractSpliterator<T> {
+    private final long limit;
+    private final Spliterator<T> original;
+    private int position = 0;
+
+    public LimitSpliterator(long limit, Spliterator<T> original) {
+      super(
+          original.hasCharacteristics(Spliterator.SIZED)
+              ? Math.min(original.estimateSize(), limit)
+              : Long.MAX_VALUE,
+          original.characteristics()
+      );
+      this.limit = limit;
+      this.original = original;
+    }
+
+    @Override
+    public Comparator<? super T> getComparator() {
+      return original.getComparator();
+    }
+
+    @Override
+    public boolean tryAdvance(Consumer<? super T> action) {
+      if (limit <= position) {
+        return false;
+      }
+      boolean result = original.tryAdvance(action);
+      position++;
+      return result;
+    }
+  }
+
+  /**
+   * Main implementation of Stream, wrapping a single spliterator and an optional parent stream.
+   * @param <T>
+   */
+  static class StreamSource<T> extends TerminatableStream<StreamSource<T>> implements Stream<T> {
+    private final Spliterator<T> spliterator;
+
+    public StreamSource(TerminatableStream<?> prev, Spliterator<T> spliterator) {
+      super(prev);
+      this.spliterator = spliterator;
+    }
+
+    // terminal
+    @Override
+    public Spliterator<T> spliterator() {
+      terminate();
+      return spliterator;
+    }
+
+    @Override
+    public Iterator<T> iterator() {
+      return Spliterators.iterator(spliterator());
+    }
+
+    @Override
+    public long count() {
+      terminate();
+      long count = 0;
+      while (spliterator.tryAdvance(a -> { })) {
+        count++;
+      }
+      return count;
+    }
+
+    @Override
+    public void forEach(Consumer<? super T> action) {
+      forEachOrdered(action);
+    }
+
+    @Override
+    public void forEachOrdered(Consumer<? super T> action) {
+      terminate();
+      spliterator.forEachRemaining(action);
+    }
+
+    @Override
+    public Object[] toArray() {
+      return toArray(Object[]::new);
+    }
+
+    @Override
+    public <A> A[] toArray(IntFunction<A[]> generator) {
+      List<T> collected = collect(Collectors.toList());
+      return collected.toArray(generator.apply(collected.size()));
+    }
+
+    @Override
+    public <R> R collect(Supplier<R> supplier,
+                         BiConsumer<R, ? super T> accumulator,
+                         BiConsumer<R, R> combiner) {
+      return collect(Collector.of(supplier, accumulator, (a, b) -> {
+        combiner.accept(a, b);
+        return a;
+      }));
+    }
+
+    @Override
+    public <R, A> R collect(final Collector<? super T, A, R> collector) {
+      return collector.finisher().apply(reduce(
+          collector.supplier().get(),
+          (a, t) -> {
+            collector.accumulator().accept(a, t);
+            return a;
+          },
+          collector.combiner()
+      ));
+    }
+
+    @Override
+    public Optional<T> findFirst() {
+      terminate();
+      ValueConsumer<T> holder = new ValueConsumer<T>();
+      if (spliterator.tryAdvance(holder)) {
+        return Optional.of(holder.value);
+      }
+      return Optional.empty();
+    }
+
+    @Override
+    public Optional<T> findAny() {
+      return findFirst();
+    }
+
+    @Override
+    public boolean anyMatch(Predicate<? super T> predicate) {
+      return filter(predicate).findFirst().isPresent();
+    }
+
+    @Override
+    public boolean allMatch(final Predicate<? super T> predicate) {
+      return !anyMatch(predicate.negate());
+    }
+
+    @Override
+    public boolean noneMatch(final Predicate<? super T> predicate) {
+      return !anyMatch(predicate);
+    }
+
+    @Override
+    public Optional<T> min(final Comparator<? super T> comparator) {
+      return reduce(BinaryOperator.minBy(comparator));
+    }
+
+    @Override
+    public Optional<T> max(final Comparator<? super T> comparator) {
+      return reduce(BinaryOperator.maxBy(comparator));
+    }
+
+    @Override
+    public T reduce(T identity, BinaryOperator<T> accumulator) {
+      return reduce(identity, accumulator, accumulator);
+    }
+
+    @Override
+    public Optional<T> reduce(BinaryOperator<T> accumulator) {
+      ValueConsumer<T> consumer = new ValueConsumer<T>();
+      if (!spliterator.tryAdvance(consumer)) {
+        terminate();
+        return Optional.empty();
+      }
+      return Optional.of(reduce(consumer.value, accumulator));
+    }
+
+    // combiner is ignored, since we don't parallelize
+    @Override
+    public <U> U reduce(U identity,
+                        BiFunction<U, ? super T, U> accumulator,
+                        BinaryOperator<U> combiner) {
+      terminate();
+      final ValueConsumer<U> consumer = new ValueConsumer<U>();
+      consumer.value = identity;
+      spliterator.forEachRemaining(item -> {
+        consumer.accept(accumulator.apply(consumer.value, item));
+      });
+      return consumer.value;
+    }
+    // end terminal
+
+    // intermediate
+    @Override
+    public Stream<T> filter(Predicate<? super T> predicate) {
+      throwIfTerminated();
+      return new StreamSource<>(this, new FilterSpliterator<>(predicate, spliterator));
+    }
+
+    @Override
+    public <R> Stream<R> map(Function<? super T, ? extends R> mapper) {
+      throwIfTerminated();
+      return new StreamSource<>(this, new MapToObjSpliterator<>(mapper, spliterator));
+    }
+
+    @Override
+    public IntStream mapToInt(ToIntFunction<? super T> mapper) {
+      throwIfTerminated();
+      return new IntStream.IntStreamSource(this, new MapToIntSpliterator<>(mapper, spliterator));
+    }
+
+    @Override
+    public LongStream mapToLong(ToLongFunction<? super T> mapper) {
+      throwIfTerminated();
+      return new LongStream.LongStreamSource(this, new MapToLongSpliterator<>(mapper, spliterator));
+    }
+
+    @Override
+    public DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper) {
+      throwIfTerminated();
+      return new DoubleStream.DoubleStreamSource(
+          this,
+          new MapToDoubleSpliterator<>(mapper, spliterator)
+      );
+    }
+
+    @Override
+    public <R> Stream<R> flatMap(final Function<? super T, ? extends Stream<? extends R>> mapper) {
+      throwIfTerminated();
+      final Spliterator<? extends Stream<? extends R>> spliteratorOfStreams =
+          new MapToObjSpliterator<>(mapper, spliterator);
+      return new StreamSource<R>(this, new Spliterators.AbstractSpliterator<R>(Long.MAX_VALUE, 0) {
+        Stream<? extends R> nextStream;
+        Spliterator<? extends R> next;
+
+        @Override
+        public boolean tryAdvance(Consumer<? super R> action) {
+          // look for a new spliterator
+          while (advanceToNextSpliterator()) {
+            // if we have one, try to read and use it
+            if (next.tryAdvance(action)) {
+              return true;
+            } else {
+              nextStream.close();
+              nextStream = null;
+              // failed, null it out so we can find another
+              next = null;
+            }
+          }
+          return false;
+        }
+
+        private boolean advanceToNextSpliterator() {
+          while (next == null) {
+            if (!spliteratorOfStreams.tryAdvance(n -> {
+              if (n != null) {
+                nextStream = n;
+                next = n.spliterator();
+              }
+            })) {
+              return false;
+            }
+          }
+          return true;
+        }
+      });
+    }
+
+    @Override
+    public IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper) {
+      throwIfTerminated();
+      final Spliterator<? extends IntStream> spliteratorOfStreams =
+          new MapToObjSpliterator<>(mapper, spliterator);
+      return new IntStream.IntStreamSource(
+          this,
+          new Spliterators.AbstractIntSpliterator(Long.MAX_VALUE, 0) {
+            IntStream nextStream;
+            Spliterator.OfInt next;
+
+            @Override
+            public boolean tryAdvance(IntConsumer action) {
+              // look for a new spliterator
+              while (advanceToNextSpliterator()) {
+                // if we have one, try to read and use it
+                if (next.tryAdvance(action)) {
+                  return true;
+                } else {
+                  nextStream.close();
+                  nextStream = null;
+                  // failed, null it out so we can find another
+                  next = null;
+                }
+              }
+              return false;
+            }
+
+            private boolean advanceToNextSpliterator() {
+              while (next == null) {
+                if (!spliteratorOfStreams.tryAdvance(n -> {
+                  if (n != null) {
+                    nextStream = n;
+                    next = n.spliterator();
+                  }
+                })) {
+                  return false;
+                }
+              }
+              return true;
+            }
+          }
+      );
+    }
+
+    @Override
+    public LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper) {
+      throwIfTerminated();
+      final Spliterator<? extends LongStream> spliteratorOfStreams =
+          new MapToObjSpliterator<>(mapper, spliterator);
+      return new LongStream.LongStreamSource(
+          this,
+          new Spliterators.AbstractLongSpliterator(Long.MAX_VALUE, 0) {
+            LongStream nextStream;
+            Spliterator.OfLong next;
+
+            @Override
+            public boolean tryAdvance(LongConsumer action) {
+              // look for a new spliterator
+              while (advanceToNextSpliterator()) {
+                // if we have one, try to read and use it
+                if (next.tryAdvance(action)) {
+                  return true;
+                } else {
+                  nextStream.close();
+                  nextStream = null;
+                  // failed, null it out so we can find another
+                  next = null;
+                }
+              }
+              return false;
+            }
+
+            private boolean advanceToNextSpliterator() {
+              while (next == null) {
+                if (!spliteratorOfStreams.tryAdvance(n -> {
+                  if (n != null) {
+                    nextStream = n;
+                    next = n.spliterator();
+                  }
+                })) {
+                  return false;
+                }
+              }
+              return true;
+            }
+          }
+      );
+    }
+
+    @Override
+    public DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper) {
+      throwIfTerminated();
+      final Spliterator<? extends DoubleStream> spliteratorOfStreams =
+          new MapToObjSpliterator<>(mapper, spliterator);
+      return new DoubleStream.DoubleStreamSource(
+          this,
+          new Spliterators.AbstractDoubleSpliterator(Long.MAX_VALUE, 0) {
+            DoubleStream nextStream;
+            Spliterator.OfDouble next;
+
+            @Override
+            public boolean tryAdvance(DoubleConsumer action) {
+              // look for a new spliterator
+              while (advanceToNextSpliterator()) {
+                // if we have one, try to read and use it
+                if (next.tryAdvance(action)) {
+                  return true;
+                } else {
+                  nextStream.close();
+                  nextStream = null;
+                  // failed, null it out so we can find another
+                  next = null;
+                }
+              }
+              return false;
+            }
+
+            private boolean advanceToNextSpliterator() {
+              while (next == null) {
+                if (!spliteratorOfStreams.tryAdvance(n -> {
+                  if (n != null) {
+                    nextStream = n;
+                    next = n.spliterator();
+                  }
+                })) {
+                  return false;
+                }
+              }
+              return true;
+            }
+          }
+      );
+    }
+
+    @Override
+    public Stream<T> distinct() {
+      throwIfTerminated();
+      HashSet<T> seen = new HashSet<>();
+      return filter(seen::add);
+    }
+
+    @Override
+    public Stream<T> sorted() {
+      throwIfTerminated();
+      Comparator<T> c = (Comparator) Comparator.naturalOrder();
+      return sorted(c);
+    }
+
+    @Override
+    public Stream<T> sorted(final Comparator<? super T> comparator) {
+      throwIfTerminated();
+      return new StreamSource<>(
+          this,
+          new Spliterators.AbstractSpliterator<T>(
+              spliterator.estimateSize(),
+              spliterator.characteristics() | Spliterator.SORTED
+          ) {
+            Spliterator<T> ordered = null;
+
+            @Override
+            public Comparator<? super T> getComparator() {
+              return comparator == Comparator.naturalOrder() ? null : comparator;
+            }
+
+            @Override
+            public boolean tryAdvance(Consumer<? super T> action) {
+              if (ordered == null) {
+                List<T> list = new ArrayList<>();
+                spliterator.forEachRemaining(list::add);
+                Collections.sort(list, comparator);
+                ordered = list.spliterator();
+              }
+              return ordered.tryAdvance(action);
+            }
+          }
+      );
+    }
+
+    @Override
+    public Stream<T> peek(final Consumer<? super T> action) {
+      checkNotNull(action);
+      throwIfTerminated();
+      return new StreamSource<>(
+          this,
+          new Spliterators.AbstractSpliterator<T>(
+              spliterator.estimateSize(),
+              spliterator.characteristics()
+          ) {
+            @Override
+            public boolean tryAdvance(final Consumer<? super T> innerAction) {
+              return spliterator.tryAdvance(item -> {
+                action.accept(item);
+                innerAction.accept(item);
+              });
+            }
+          }
+      );
+    }
+
+    @Override
+    public Stream<T> limit(long maxSize) {
+      throwIfTerminated();
+      checkState(maxSize >= 0, "maxSize may not be negative");
+      return new StreamSource<>(this, new LimitSpliterator<>(maxSize, spliterator));
+    }
+
+    @Override
+    public Stream<T> skip(long n) {
+      throwIfTerminated();
+      checkState(n >= 0, "n may not be negative");
+      if (n == 0) {
+        return this;
+      }
+      return new StreamSource<>(this, new SkipSpliterator<>(n, spliterator));
+    }
+
+    @Override
+    public boolean isParallel() {
+      throwIfTerminated();
+      return false;
+    }
+
+    @Override
+    public Stream<T> sequential() {
+      throwIfTerminated();
+      return this;
+    }
+
+    @Override
+    public Stream<T> parallel() {
+      throwIfTerminated();
+      // do nothing, no such thing as gwt+parallel
+      return this;
+    }
+
+    @Override
+    public Stream<T> unordered() {
+      throwIfTerminated();
+      return this;
+    }
+  }
+}
diff --git a/user/super/com/google/gwt/emul/java/util/stream/StreamSupport.java b/user/super/com/google/gwt/emul/java/util/stream/StreamSupport.java
new file mode 100644
index 0000000..12b34e3
--- /dev/null
+++ b/user/super/com/google/gwt/emul/java/util/stream/StreamSupport.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package java.util.stream;
+
+import java.util.Spliterator;
+import java.util.function.Supplier;
+
+/**
+ * See <a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/StreamSupport.html">
+ * the official Java API doc</a> for details.
+ */
+public final class StreamSupport {
+
+  public static DoubleStream doubleStream(Spliterator.OfDouble spliterator, boolean parallel) {
+    return new DoubleStream.DoubleStreamSource(null, spliterator);
+  }
+
+  public static DoubleStream doubleStream(Supplier<? extends Spliterator.OfDouble> supplier,
+                                          int characteristics,
+                                          boolean parallel) {
+    // TODO this is somewhat convoluted, and would be better served by a lazy singleton spliterator
+    return Stream.of(supplier).map(Supplier::get).flatMapToDouble(doubleSpliterator -> {
+      return doubleStream(doubleSpliterator, parallel);
+    });
+  }
+
+  public static IntStream intStream(Spliterator.OfInt spliterator, boolean parallel) {
+    return new IntStream.IntStreamSource(null, spliterator);
+  }
+
+  public static IntStream intStream(Supplier<? extends Spliterator.OfInt> supplier,
+                                    int characteristics,
+                                    boolean parallel) {
+    // TODO this is somewhat convoluted, and would be better served by a lazy singleton spliterator
+    return Stream.of(supplier).map(Supplier::get).flatMapToInt(intSpliterator -> {
+      return intStream(intSpliterator, parallel);
+    });
+  }
+
+  public static LongStream longStream(Spliterator.OfLong spliterator, boolean parallel) {
+    return new LongStream.LongStreamSource(null, spliterator);
+  }
+
+  public static LongStream longStream(Supplier<? extends Spliterator.OfLong> supplier,
+                                      int characteristics,
+                                      final boolean parallel) {
+    // TODO this is somewhat convoluted, and would be better served by a lazy singleton spliterator
+    return Stream.of(supplier).map(Supplier::get).flatMapToLong(longSpliterator -> {
+      return longStream(longSpliterator, parallel);
+    });
+  }
+
+  public static <T> Stream<T> stream(Spliterator<T> spliterator, boolean parallel) {
+    return new Stream.StreamSource<T>(null, spliterator);
+  }
+
+  public static <T> Stream<T> stream(Supplier<? extends Spliterator<T>> supplier,
+                                     int characteristics,
+                                     final boolean parallel) {
+    // TODO this is somewhat convoluted, and would be better served by a lazy singleton spliterator
+    return Stream.of(supplier).map(Supplier::get).flatMap(spliterator -> {
+      return stream(spliterator, parallel);
+    });
+  }
+
+  private StreamSupport() {
+    // prevent instantiation
+  }
+
+}
diff --git a/user/super/com/google/gwt/emul/java/util/stream/TerminatableStream.java b/user/super/com/google/gwt/emul/java/util/stream/TerminatableStream.java
new file mode 100644
index 0000000..018331f
--- /dev/null
+++ b/user/super/com/google/gwt/emul/java/util/stream/TerminatableStream.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package java.util.stream;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+
+// package protected, as not part of jre
+class TerminatableStream<T extends TerminatableStream<T>> {
+  // root-only fields, ignored for non-root instances
+  private boolean terminated = false;
+  private final List<Runnable> onClose;
+
+  private final TerminatableStream<?> root;
+
+  public TerminatableStream(TerminatableStream<?> previous) {
+    if (previous == null) {
+      root = null;
+      onClose = new ArrayList<>();
+    } else {
+      root = previous;
+      onClose = null;
+    }
+  }
+
+  void throwIfTerminated() {
+    if (root != null) {
+      root.throwIfTerminated();
+    } else if (terminated) {
+      throw new IllegalStateException("Stream already terminated, can't be modified or used");
+    }
+  }
+
+  // note that not all terminals directly call this, but they must use it indirectly
+  void terminate() {
+    if (root == null) {
+      throwIfTerminated();
+      terminated = true;
+    } else {
+      root.terminate();
+    }
+  }
+
+  public T onClose(Runnable closeHandler) {
+    if (root == null) {
+      onClose.add(closeHandler);
+    } else {
+      root.onClose(closeHandler);
+    }
+
+    return (T) this;
+  }
+
+  public void close() {
+    if (root == null) {
+      terminated = true;
+
+      // TODO this might not be quite right, make sure that it behaves the same way when throwing
+      //      the same exception multiple times as JDK does.
+      LinkedHashSet<Throwable> throwables = new LinkedHashSet<>();
+      onClose.forEach((runnable) -> {
+        try {
+          runnable.run();
+        } catch (Throwable e) {
+          throwables.add(e);
+        }
+      });
+      onClose.clear();
+      if (!throwables.isEmpty()) {
+        Iterator<Throwable> iterator = throwables.iterator();
+        Throwable outer = iterator.next();
+        iterator.forEachRemaining(outer::addSuppressed);
+
+        if (outer instanceof RuntimeException) {
+          throw (RuntimeException) outer;
+        }
+        if (outer instanceof Error) {
+          throw (Error) outer;
+        }
+        assert false : "Couldn't have caught this exception from a Runnable! " + outer;
+      }
+    } else {
+      root.close();
+    }
+  }
+}
\ No newline at end of file
diff --git a/user/test/com/google/gwt/emultest/EmulJava8Suite.java b/user/test/com/google/gwt/emultest/EmulJava8Suite.java
index e898b30..572eb86 100644
--- a/user/test/com/google/gwt/emultest/EmulJava8Suite.java
+++ b/user/test/com/google/gwt/emultest/EmulJava8Suite.java
@@ -43,6 +43,11 @@
 import com.google.gwt.emultest.java8.util.TreeMapTest;
 import com.google.gwt.emultest.java8.util.VectorTest;
 import com.google.gwt.emultest.java8.util.stream.CollectorsTest;
+import com.google.gwt.emultest.java8.util.stream.DoubleStreamTest;
+import com.google.gwt.emultest.java8.util.stream.IntStreamTest;
+import com.google.gwt.emultest.java8.util.stream.LongStreamTest;
+import com.google.gwt.emultest.java8.util.stream.StreamSupportTest;
+import com.google.gwt.emultest.java8.util.stream.StreamTest;
 import com.google.gwt.junit.tools.GWTTestSuite;
 
 import junit.framework.Test;
@@ -90,6 +95,11 @@
 
     //-- java.util.stream
     suite.addTestSuite(CollectorsTest.class);
+    suite.addTestSuite(DoubleStreamTest.class);
+    suite.addTestSuite(IntStreamTest.class);
+    suite.addTestSuite(LongStreamTest.class);
+    suite.addTestSuite(StreamTest.class);
+    suite.addTestSuite(StreamSupportTest.class);
 
     return suite;
   }
diff --git a/user/test/com/google/gwt/emultest/java/util/EmulTestBase.java b/user/test/com/google/gwt/emultest/java/util/EmulTestBase.java
index a3babcc..c1fc5de 100644
--- a/user/test/com/google/gwt/emultest/java/util/EmulTestBase.java
+++ b/user/test/com/google/gwt/emultest/java/util/EmulTestBase.java
@@ -17,6 +17,7 @@
 
 import com.google.gwt.junit.client.GWTTestCase;
 
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -41,6 +42,21 @@
     }
   }
 
+  public static void assertEquals(int[] expected, int[] actual) {
+    assertTrue("expected: " + Arrays.toString(expected) + ", actual: " + Arrays.toString(actual),
+        Arrays.equals(expected, actual));
+  }
+
+  public static void assertEquals(long[] expected, long[] actual) {
+    assertTrue("expected: " + Arrays.toString(expected) + ", actual: " + Arrays.toString(actual),
+        Arrays.equals(expected, actual));
+  }
+
+  public static void assertEquals(double[] expected, double[] actual) {
+    assertTrue("expected: " + Arrays.toString(expected) + ", actual: " + Arrays.toString(actual),
+        Arrays.equals(expected, actual));
+  }
+
   @Override
   public String getModuleName() {
     return "com.google.gwt.emultest.EmulSuite";
diff --git a/user/test/com/google/gwt/emultest/java8/util/ArraysTest.java b/user/test/com/google/gwt/emultest/java8/util/ArraysTest.java
index 3a4d42b..ffb42dd 100644
--- a/user/test/com/google/gwt/emultest/java8/util/ArraysTest.java
+++ b/user/test/com/google/gwt/emultest/java8/util/ArraysTest.java
@@ -135,4 +135,156 @@
     Arrays.setAll(array, i -> "" + (i + 1));
     assertEquals(new String[]{"1", "2", "3"}, array);
   }
+
+  public void testArrayStreamInt() {
+    int[] six = {1, 2, 3, 4, 5, 6};
+
+    // zero entries
+    assertEquals(new int[]{}, Arrays.stream(six, 0, 0).toArray());
+    assertEquals(new int[]{}, Arrays.stream(six, 1, 1).toArray());
+
+    // single entry
+    assertEquals(new int[]{1}, Arrays.stream(six, 0, 1).toArray());
+    assertEquals(new int[]{2}, Arrays.stream(six, 1, 2).toArray());
+
+    // multiple entries
+    assertEquals(new int[]{1, 2, 3}, Arrays.stream(six, 0, 3).toArray());
+    assertEquals(new int[]{4, 5, 6}, Arrays.stream(six, 3, 6).toArray());
+
+    try {
+      // start < 0
+      Arrays.stream(six, -1, 1);
+      fail("expected aioobe");
+    } catch (ArrayIndexOutOfBoundsException expected) {
+      // expected
+    }
+    try {
+      // end < start
+      Arrays.stream(six, 2, 1);
+      fail("expected aioobe");
+    } catch (ArrayIndexOutOfBoundsException expected) {
+      // expected
+    }
+    try {
+      // end > size
+      Arrays.stream(six, 0, 7);
+      fail("expected aioobe");
+    } catch (ArrayIndexOutOfBoundsException expected) {
+      // expected
+    }
+  }
+
+  public void testArrayStreamLong() {
+    long[] six = {1, 2, 3, 4, 5, 6};
+
+    // zero entries
+    assertEquals(new long[]{}, Arrays.stream(six, 0, 0).toArray());
+    assertEquals(new long[]{}, Arrays.stream(six, 1, 1).toArray());
+
+    // single entry
+    assertEquals(new long[]{1}, Arrays.stream(six, 0, 1).toArray());
+    assertEquals(new long[]{2}, Arrays.stream(six, 1, 2).toArray());
+
+    // multiple entries
+    assertEquals(new long[]{1, 2, 3}, Arrays.stream(six, 0, 3).toArray());
+    assertEquals(new long[]{4, 5, 6}, Arrays.stream(six, 3, 6).toArray());
+
+    try {
+      // start < 0
+      Arrays.stream(six, -1, 1);
+      fail("expected aioobe");
+    } catch (ArrayIndexOutOfBoundsException expected) {
+      // expected
+    }
+    try {
+      // end < start
+      Arrays.stream(six, 2, 1);
+      fail("expected aioobe");
+    } catch (ArrayIndexOutOfBoundsException expected) {
+      // expected
+    }
+    try {
+      // end > size
+      Arrays.stream(six, 0, 7);
+      fail("expected aioobe");
+    } catch (ArrayIndexOutOfBoundsException expected) {
+      // expected
+    }
+  }
+
+  public void testArrayStreamDouble() {
+    double[] six = {1, 2, 3, 4, 5, 6};
+
+    // zero entries
+    assertEquals(new double[]{}, Arrays.stream(six, 0, 0).toArray());
+    assertEquals(new double[]{}, Arrays.stream(six, 1, 1).toArray());
+
+    // single entry
+    assertEquals(new double[]{1}, Arrays.stream(six, 0, 1).toArray());
+    assertEquals(new double[]{2}, Arrays.stream(six, 1, 2).toArray());
+
+    // multiple entries
+    assertEquals(new double[]{1, 2, 3}, Arrays.stream(six, 0, 3).toArray());
+    assertEquals(new double[]{4, 5, 6}, Arrays.stream(six, 3, 6).toArray());
+
+    try {
+      // start < 0
+      Arrays.stream(six, -1, 1);
+      fail("expected aioobe");
+    } catch (ArrayIndexOutOfBoundsException expected) {
+      // expected
+    }
+    try {
+      // end < start
+      Arrays.stream(six, 2, 1);
+      fail("expected aioobe");
+    } catch (ArrayIndexOutOfBoundsException expected) {
+      // expected
+    }
+    try {
+      // end > size
+      Arrays.stream(six, 0, 7);
+      fail("expected aioobe");
+    } catch (ArrayIndexOutOfBoundsException expected) {
+      // expected
+    }
+  }
+
+  public void testArrayStreamObject() {
+    String[] six = {"1", "2", "3", "4", "5", "6"};
+
+    // zero entries
+    assertEquals(new String[]{}, Arrays.stream(six, 0, 0).toArray());
+    assertEquals(new String[]{}, Arrays.stream(six, 1, 1).toArray());
+
+    // single entry
+    assertEquals(new String[]{"1"}, Arrays.stream(six, 0, 1).toArray());
+    assertEquals(new String[]{"2"}, Arrays.stream(six, 1, 2).toArray());
+
+    // multiple entries
+    assertEquals(new String[]{"1", "2", "3"}, Arrays.stream(six, 0, 3).toArray());
+    assertEquals(new String[]{"4", "5", "6"}, Arrays.stream(six, 3, 6).toArray());
+
+    try {
+      // start < 0
+      Arrays.stream(six, -1, 1);
+      fail("expected aioobe");
+    } catch (ArrayIndexOutOfBoundsException expected) {
+      // expected
+    }
+    try {
+      // end < start
+      Arrays.stream(six, 2, 1);
+      fail("expected aioobe");
+    } catch (ArrayIndexOutOfBoundsException expected) {
+      // expected
+    }
+    try {
+      // end > size
+      Arrays.stream(six, 0, 7);
+      fail("expected aioobe");
+    } catch (ArrayIndexOutOfBoundsException expected) {
+      // expected
+    }
+  }
 }
diff --git a/user/test/com/google/gwt/emultest/java8/util/stream/DoubleStreamTest.java b/user/test/com/google/gwt/emultest/java8/util/stream/DoubleStreamTest.java
new file mode 100644
index 0000000..fb0cc17
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java8/util/stream/DoubleStreamTest.java
@@ -0,0 +1,443 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.emultest.java8.util.stream;
+
+import com.google.gwt.emultest.java.util.EmulTestBase;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.DoubleSummaryStatistics;
+import java.util.Iterator;
+import java.util.List;
+import java.util.OptionalDouble;
+import java.util.Spliterator;
+import java.util.function.DoubleSupplier;
+import java.util.function.Supplier;
+import java.util.stream.DoubleStream;
+import java.util.stream.Stream;
+
+/**
+ * Tests {@link DoubleStream}.
+ */
+public class DoubleStreamTest extends EmulTestBase {
+
+  public void testEmptyStream() {
+    DoubleStream empty = DoubleStream.empty();
+    assertEquals(0, empty.count());
+    try {
+      empty.count();
+      fail("second terminal operation should have thrown IllegalStateEx");
+    } catch (IllegalStateException expected) {
+      // expected
+    }
+
+    assertEquals(0, DoubleStream.empty().limit(2).toArray().length);
+    assertEquals(0L, DoubleStream.empty().count());
+    assertEquals(0L, DoubleStream.empty().limit(2).count());
+
+    assertFalse(DoubleStream.empty().findFirst().isPresent());
+    assertFalse(DoubleStream.empty().findAny().isPresent());
+    assertFalse(DoubleStream.empty().max().isPresent());
+    assertFalse(DoubleStream.empty().min().isPresent());
+    assertTrue(DoubleStream.empty().noneMatch(item -> true));
+    assertTrue(DoubleStream.empty().allMatch(item -> true));
+    assertFalse(DoubleStream.empty().anyMatch(item -> true));
+    assertEquals(new double[0], DoubleStream.empty().toArray());
+  }
+
+  public void testStreamOfOne() {
+    Supplier<DoubleStream> one = () -> DoubleStream.of(1);
+    assertEquals(new double[]{1d}, one.get().toArray());
+    assertEquals(1L, one.get().count());
+    assertEquals(1d, one.get().findFirst().getAsDouble(), 0d);
+    assertEquals(1d, one.get().findAny().getAsDouble(), 0d);
+  }
+
+  public void testBuilder() {
+    DoubleStream s = DoubleStream.builder()
+        .add(1d)
+        .add(3d)
+        .add(2d)
+        .build();
+
+    assertEquals(
+        new double[] {1d, 3d, 2d},
+        s.toArray()
+    );
+
+    DoubleStream.Builder builder = DoubleStream.builder();
+    DoubleStream built = builder.build();
+    assertEquals(0, built.count());
+    try {
+      builder.build();
+      fail("build() after build() should fail");
+    } catch (IllegalStateException expected) {
+      // expected
+    }
+    try {
+      builder.add(10d);
+      fail("add() after build() should fail");
+    } catch (IllegalStateException expected) {
+      // expected
+    }
+  }
+
+  public void testConcat() {
+    Supplier<DoubleStream> adbc = () -> {
+      return DoubleStream.concat(DoubleStream.of(1, 4), DoubleStream.of(2, 3));
+    };
+
+    assertEquals(new double[]{1d, 4d, 2d, 3d}, adbc.get().toArray());
+    assertEquals(new double[]{1d, 2d, 3d, 4d}, adbc.get().sorted().toArray());
+
+    List<String> closed = new ArrayList<>();
+    DoubleStream first = DoubleStream.of(1d).onClose(() -> closed.add("first"));
+    DoubleStream second = DoubleStream.of(2d).onClose(() -> closed.add("second"));
+
+    DoubleStream concat = DoubleStream.concat(first, second);
+
+    // read everything, make sure we saw it all and didn't close automatically
+    double collectedAll = concat.sum();
+    assertEquals(3d, collectedAll);
+    assertEquals(0, closed.size());
+
+    concat.close();
+    assertEquals(Arrays.asList("first", "second"), closed);
+  }
+
+  public void testIterate() {
+    assertEquals(
+        new double[]{10d, 11d, 12d, 13d, 14d},
+        DoubleStream.iterate(0d, l -> l + 1d)
+            .skip(10)
+            .limit(5)
+            .toArray()
+    );
+  }
+
+  public void testGenerate() {
+    // infinite, but if you limit it is already too short to skip much
+    assertEquals(new double[0], DoubleStream.generate(makeGenerator()).limit(4).skip(5).toArray());
+
+    assertEquals(
+        new double[]{10d, 11d, 12d, 13d, 14d},
+        DoubleStream.generate(makeGenerator())
+            .skip(10)
+            .limit(5)
+            .toArray()
+    );
+  }
+
+  private DoubleSupplier makeGenerator() {
+    return new DoubleSupplier() {
+      double next = 0d;
+
+      @Override
+      public double getAsDouble() {
+        return next++;
+      }
+    };
+  }
+
+  public void testToArray() {
+    assertEquals(new double[0], DoubleStream.of().toArray());
+    assertEquals(new double[] {1d}, DoubleStream.of(1d).toArray());
+    assertEquals(new double[] {3d, 2d, 0d}, DoubleStream.of(3d, 2d, 0d).toArray());
+  }
+
+  public void testReduce() {
+    double reduced = DoubleStream.of(1d, 2d, 4d).reduce(0, Double::sum);
+    assertEquals(7d, reduced, 0d);
+
+    reduced = DoubleStream.of().reduce(0, Double::sum);
+    assertEquals(0d, reduced, 0d);
+
+    OptionalDouble maybe = DoubleStream.of(1d, 4d, 8d).reduce(Double::sum);
+    assertTrue(maybe.isPresent());
+    assertEquals(13, maybe.getAsDouble(), 0d);
+    maybe = DoubleStream.of().reduce(Double::sum);
+    assertFalse(maybe.isPresent());
+  }
+
+  public void testFilter() {
+    // unconsumed stream never runs filter
+    boolean[] data = {false};
+    DoubleStream.of(1d, 2d, 3d).filter(i -> data[0] |= true);
+    assertFalse(data[0]);
+
+    // one result
+    assertEquals(
+        new double[]{1d},
+        DoubleStream.of(1d, 2d, 3d, 4d, 3d).filter(a -> a == 1).toArray()
+    );
+    // zero results
+    assertEquals(
+        new double[0],
+        DoubleStream.of(1d, 2d, 3d, 4d, 3d).filter(a -> false).toArray()
+    );
+    // two results
+    assertEquals(
+        new double[] {2d, 4d},
+        DoubleStream.of(1d, 2d, 3d, 4d, 3d).filter(a -> a % 2 == 0).toArray()
+    );
+    // all
+    assertEquals(
+        new double[] {1d, 2d, 3d, 4d, 3d},
+        DoubleStream.of(1d, 2d, 3d, 4d, 3d).filter(a -> true).toArray()
+    );
+  }
+
+  public void testMap() {
+    // unconsumed stream never runs map
+    int[] data = {0};
+    DoubleStream.of(1d, 2d, 3d).map(i -> data[0]++);
+    assertEquals(0, data[0]);
+
+    assertEquals(
+        new double[] {2d, 4d, 6d},
+        DoubleStream.of(1d, 2d, 3d).map(i -> i * 2).toArray()
+    );
+  }
+
+  public void testPeek() {
+    // unconsumed stream never peeks
+    boolean[] data = {false};
+    DoubleStream.of(1d, 2d, 3d).peek(i -> data[0] |= true);
+    assertFalse(data[0]);
+
+    // make sure we saw it all in order
+    double[] items = new double[] {1d, 2d, 3d};
+    List<Double> peeked = new ArrayList<>();
+    DoubleStream.of(items).peek(peeked::add).forEach(item -> {
+      // do nothing, just run
+    });
+    assertEquals(items.length, peeked.size());
+    for (int i = 0; i < items.length; i++) {
+      assertEquals(items[i], peeked.get(i), 0d);
+    }
+  }
+
+  // same impl, no parallel in browser
+  public void testFindFirstOrAny() {
+    OptionalDouble any = DoubleStream.of(1d, 2d).findAny();
+    assertTrue(any.isPresent());
+    assertEquals(1d, any.getAsDouble(), 0d);
+  }
+
+  public void testAnyMatch() {
+    // all
+    assertTrue(DoubleStream.of(1d, 2d).anyMatch(s -> true));
+
+    // some
+    assertTrue(DoubleStream.of(1d, 2d).anyMatch(s -> s == 1d));
+
+    // none
+    assertFalse(DoubleStream.of(1d, 2d).anyMatch(s -> false));
+  }
+
+  public void testAllMatch() {
+    // all
+    assertTrue(DoubleStream.of(1d, 2d).allMatch(s -> true));
+
+    // some
+    assertFalse(DoubleStream.of(1d, 2d).allMatch(s -> s == 1d));
+
+    // none
+    assertFalse(DoubleStream.of(1d, 2d).allMatch(s -> false));
+  }
+
+  public void testNoneMatch() {
+    // all
+    assertFalse(DoubleStream.of(1d, 2d).noneMatch(s -> true));
+
+    // some
+    assertFalse(DoubleStream.of(1d, 2d).noneMatch(s -> s == 1d));
+
+    // none
+    assertTrue(DoubleStream.of(1d, 2d).noneMatch(s -> false));
+  }
+
+  public void testFlatMap() {
+    assertEquals(0L, DoubleStream.empty().flatMap(value -> DoubleStream.of(1d)).count());
+    assertEquals(0L, DoubleStream.of(1d).flatMap(value -> DoubleStream.empty()).count());
+    assertEquals(0L, DoubleStream.of(1d).flatMap(value -> DoubleStream.of()).count());
+    assertEquals(0L, DoubleStream.of().flatMap(value -> DoubleStream.of(1d)).count());
+    assertEquals(1L, DoubleStream.of(1d).flatMap(value -> DoubleStream.of(1d)).count());
+
+    DoubleStream values = DoubleStream.of(1d, 2d, 3d);
+
+    assertEquals(
+        new double[] {1d, 2d, 2d, 4d, 3d, 6d},
+        values.flatMap(i -> DoubleStream.of(i, i * 2d)).toArray()
+    );
+  }
+
+  public void testMapToOthers() {
+    Supplier<DoubleStream> s = () -> DoubleStream.of(1d, 2d, 10d);
+
+    assertEquals(
+        new String[]{"1", "2", "10"},
+        s.get().mapToObj(DoubleStreamTest::toIntegralString).toArray(String[]::new)
+    );
+
+    assertEquals(
+        new long[]{1L, 2L, 10L},
+        s.get().mapToLong(i -> (long) i).toArray()
+    );
+
+    assertEquals(
+        new int[] {1, 2, 10},
+        s.get().mapToInt(i -> (int) i).toArray()
+    );
+  }
+
+  public void testDistinct() {
+    double[] distinct = DoubleStream.of(1d, 2d, 3d, 2d).distinct().toArray();
+    assertEquals(3, distinct.length);
+    assertEquals(1d + 2d + 3d, distinct[0] + distinct[1] + distinct[2], 0d);
+  }
+
+  public void testSorted() {
+    double[] sorted = DoubleStream.of(3d, 1d, 2d).sorted().toArray();
+    assertEquals(new double[] {1d, 2d, 3d}, sorted);
+  }
+
+  public void testMinMax() {
+    Supplier<DoubleStream> stream = () -> DoubleStream.of(2d, 3d, 4d, 1d);
+
+    assertEquals(1d, stream.get().min().orElse(0), 0d);
+    assertEquals(4d, stream.get().max().orElse(0), 0d);
+
+    assertFalse(stream.get().filter(a -> false).max().isPresent());
+    assertFalse(stream.get().filter(a -> false).min().isPresent());
+  }
+
+  public void testCountLimitSkip() {
+    Supplier<DoubleStream> stream = () -> DoubleStream.of(1d, 2d, 3d, 4d);
+
+    assertEquals(4L, stream.get().count());
+
+    assertEquals(4L, stream.get().limit(4).count());
+    assertEquals(4L, stream.get().limit(5).count());
+    assertEquals(3L, stream.get().limit(3).count());
+
+    assertEquals(3L, stream.get().skip(1).limit(3).count());
+
+    assertEquals(2L, stream.get().limit(3).skip(1).count());
+
+    assertEquals(1L, stream.get().skip(3).count());
+
+    assertEquals(new double[] {3d, 4d}, stream.get().skip(2).limit(3).toArray());
+    assertEquals(new double[] {3d}, stream.get().skip(2).limit(1).toArray());
+
+    assertEquals(new double[] {4d}, stream.get().skip(3).toArray());
+    assertEquals(new double[] {}, stream.get().skip(5).toArray());
+
+    assertEquals(new double[] {1d, 2d}, stream.get().limit(2).toArray());
+
+    assertEquals(new double[] {2d}, stream.get().limit(2).skip(1).toArray());
+  }
+
+  public void testBoxed() {
+    Supplier<DoubleStream> stream = () -> DoubleStream.of(1d, 2d);
+    Stream<Double> expected = stream.get().mapToObj(Double::valueOf);
+    assertEquals(expected.toArray(), stream.get().boxed().toArray());
+  }
+
+  public void testSummaryStats() {
+    Supplier<DoubleStream> stream = () -> DoubleStream.of(1d, 2d, 3d);
+    DoubleSummaryStatistics summaryStats = stream.get().summaryStatistics();
+    assertEquals(3L, summaryStats.getCount());
+    assertEquals(1d, summaryStats.getMin(), 0d);
+    assertEquals(2d, summaryStats.getAverage(), 0d);
+    assertEquals(3d, summaryStats.getMax(), 0d);
+    assertEquals(6d, summaryStats.getSum(), 0d);
+
+    summaryStats.accept(6L);
+    assertEquals(4L, summaryStats.getCount());
+    assertEquals(1d, summaryStats.getMin(), 0d);
+    assertEquals(3d, summaryStats.getAverage(), 0d);
+    assertEquals(6d, summaryStats.getMax(), 0d);
+    assertEquals(12d, summaryStats.getSum(), 0d);
+
+    DoubleSummaryStatistics combinedSumStats = stream.get().summaryStatistics();
+    combinedSumStats.combine(DoubleStream.of(4d, 5d, 6d, 0d).summaryStatistics());
+    assertEquals(7L, combinedSumStats.getCount());
+    assertEquals(0d, combinedSumStats.getMin(), 0d);
+    assertEquals(3d, combinedSumStats.getAverage(), 0d);
+    assertEquals(6d, combinedSumStats.getMax(), 0d);
+    assertEquals(21d, combinedSumStats.getSum(), 0d);
+  }
+
+  public void testAverage() {
+    assertFalse(DoubleStream.empty().average().isPresent());
+    assertEquals(2.0d, DoubleStream.of(1d, 2d, 3d).average().getAsDouble(), 0d);
+    assertEquals(0d, DoubleStream.of(1d, 2d, -3d).average().getAsDouble(), 0d);
+    assertEquals(-2.0d, DoubleStream.of(-1d, -2d, -3d).average().getAsDouble(), 0d);
+  }
+
+  public void testSum() {
+    assertEquals(6d, DoubleStream.of(1d, 2d, 3d).sum(), 0d);
+    assertEquals(0d, DoubleStream.of(1d, 2d, -3d).sum(), 0d);
+    assertEquals(-6d, DoubleStream.of(-1d, -2d, -3d).sum(), 0d);
+  }
+
+  public void testCollect() {
+    // noinspection StringConcatenationInsideStringBufferAppend
+    String val = DoubleStream.of(1d, 2d, 3d, 4d, 5d).collect(StringBuilder::new,
+        (stringBuilder, d) -> stringBuilder.append(toIntegralString(d)),
+        StringBuilder::append).toString();
+
+    assertEquals("12345", val);
+  }
+
+  public void testForEach() {
+    List<Double> vals = new ArrayList<>();
+    DoubleStream.of(1d, 2d, 3d, 4d, 5d).forEach(vals::add);
+    assertEquals(5, vals.size());
+    assertEquals(new Double[] {1d, 2d, 3d, 4d, 5d}, vals.toArray(new Double[vals.size()]));
+  }
+
+  public void testIterator() {
+    List<Double> vals = new ArrayList<>();
+    Iterator<Double> iterator = DoubleStream.of(1d, 2d, 3d, 4d, 5d).iterator();
+    while (iterator.hasNext()) {
+      vals.add(iterator.next());
+    }
+    assertEquals(5, vals.size());
+    assertEquals(new Double[] {1d, 2d, 3d, 4d, 5d}, vals.toArray(new Double[vals.size()]));
+  }
+
+  public void testSpliterator() {
+    Spliterator<Double> spliterator = DoubleStream.of(1d, 2d, 3d, 4d, 5d).spliterator();
+    assertEquals(5, spliterator.estimateSize());
+    assertEquals(5, spliterator.getExactSizeIfKnown());
+
+    List<Double> vals = new ArrayList<>();
+    while (spliterator.tryAdvance(vals::add)) {
+      // work is all done in the condition
+    }
+
+    assertEquals(5, vals.size());
+    assertEquals(new Double[] {1d, 2d, 3d, 4d, 5d}, vals.toArray(new Double[vals.size()]));
+  }
+
+  // See https://github.com/gwtproject/gwt/issues/8615
+  private static String toIntegralString(double value) {
+    return "" + (int) value;
+  }
+}
diff --git a/user/test/com/google/gwt/emultest/java8/util/stream/IntStreamTest.java b/user/test/com/google/gwt/emultest/java8/util/stream/IntStreamTest.java
new file mode 100644
index 0000000..232aebe
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java8/util/stream/IntStreamTest.java
@@ -0,0 +1,462 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.emultest.java8.util.stream;
+
+import com.google.gwt.emultest.java.util.EmulTestBase;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.IntSummaryStatistics;
+import java.util.Iterator;
+import java.util.List;
+import java.util.OptionalInt;
+import java.util.Spliterator;
+import java.util.function.IntSupplier;
+import java.util.function.Supplier;
+import java.util.stream.DoubleStream;
+import java.util.stream.IntStream;
+import java.util.stream.LongStream;
+import java.util.stream.Stream;
+
+/**
+ * Tests {@link IntStream}.
+ */
+public class IntStreamTest extends EmulTestBase {
+
+  public void testEmptyStream() {
+    IntStream empty = IntStream.empty();
+    assertEquals(0, empty.count());
+    try {
+      empty.count();
+      fail("second terminal operation should have thrown IllegalStateEx");
+    } catch (IllegalStateException expected) {
+      // expected
+    }
+
+    assertEquals(0, IntStream.empty().limit(2).toArray().length);
+    assertEquals(0L, IntStream.empty().count());
+    assertEquals(0L, IntStream.empty().limit(2).count());
+
+    assertFalse(IntStream.empty().findFirst().isPresent());
+    assertFalse(IntStream.empty().findAny().isPresent());
+    assertFalse(IntStream.empty().max().isPresent());
+    assertFalse(IntStream.empty().min().isPresent());
+    assertTrue(IntStream.empty().noneMatch(item -> true));
+    assertTrue(IntStream.empty().allMatch(item -> true));
+    assertFalse(IntStream.empty().anyMatch(item -> true));
+    assertEquals(new int[0], IntStream.empty().toArray());
+  }
+
+  public void testStreamOfOne() {
+    Supplier<IntStream> one = () -> IntStream.of(1);
+    assertEquals(new int[]{1}, one.get().toArray());
+    assertEquals(1L, one.get().count());
+    assertEquals(1, one.get().findFirst().getAsInt());
+    assertEquals(1, one.get().findAny().getAsInt());
+  }
+
+  public void testBuilder() {
+    IntStream s = IntStream.builder()
+        .add(1)
+        .add(3)
+        .add(2)
+        .build();
+
+    assertEquals(
+        new int[] {1, 3, 2},
+        s.toArray()
+    );
+
+    IntStream.Builder builder = IntStream.builder();
+    IntStream built = builder.build();
+    assertEquals(0, built.count());
+    try {
+      builder.build();
+      fail("build() after build() should fail");
+    } catch (IllegalStateException expected) {
+      // expected
+    }
+    try {
+      builder.add(10);
+      fail("add() after build() should fail");
+    } catch (IllegalStateException expected) {
+      // expected
+    }
+  }
+
+  public void testConcat() {
+    Supplier<IntStream> adbc = () -> IntStream.concat(IntStream.of(1, 4), IntStream.of(2, 3));
+
+    assertEquals(new int[]{1, 4, 2, 3}, adbc.get().toArray());
+    assertEquals(new int[]{1, 2, 3, 4}, adbc.get().sorted().toArray());
+
+    List<String> closed = new ArrayList<>();
+    IntStream first = IntStream.of(1).onClose(() -> closed.add("first"));
+    IntStream second = IntStream.of(2).onClose(() -> closed.add("second"));
+
+    IntStream concat = IntStream.concat(first, second);
+
+    // read everything, make sure we saw it all and didn't close automatically
+    int collectedAll = concat.sum();
+    assertEquals(3, collectedAll);
+    assertEquals(0, closed.size());
+
+    concat.close();
+    assertEquals(Arrays.asList("first", "second"), closed);
+  }
+
+  public void testIterate() {
+    assertEquals(
+        new int[]{10, 11, 12, 13, 14},
+        IntStream.iterate(0, i -> i + 1)
+            .skip(10)
+            .limit(5)
+            .toArray()
+    );
+  }
+
+  public void testGenerate() {
+    // infinite, but if you limit it is already too short to skip much
+    assertEquals(new int[0], IntStream.generate(makeGenerator()).limit(4).skip(5).toArray());
+
+    assertEquals(
+        new int[] {10, 11, 12, 13, 14},
+        IntStream.generate(makeGenerator())
+            .skip(10)
+            .limit(5)
+            .toArray()
+    );
+  }
+
+  private IntSupplier makeGenerator() {
+    return new IntSupplier() {
+      int next = 0;
+
+      @Override
+      public int getAsInt() {
+        return next++;
+      }
+    };
+  }
+
+  public void testRange() {
+    assertEquals(new int[] {1, 2, 3, 4}, IntStream.range(1, 5).toArray());
+    assertEquals(new int[] {-1, 0, 1, 2, 3, 4}, IntStream.range(-1, 5).toArray());
+    assertEquals(new int[] {}, IntStream.range(1, -5).toArray());
+    assertEquals(new int[] {}, IntStream.range(-1, -5).toArray());
+  }
+
+  public void testRangeClosed() {
+    assertEquals(new int[] {1, 2, 3, 4, 5}, IntStream.rangeClosed(1, 5).toArray());
+    assertEquals(new int[] {-1, 0, 1, 2, 3, 4, 5}, IntStream.rangeClosed(-1, 5).toArray());
+    assertEquals(new int[] {}, IntStream.rangeClosed(1, -5).toArray());
+    assertEquals(new int[] {}, IntStream.rangeClosed(-1, -5).toArray());
+  }
+
+  public void testToArray() {
+    assertEquals(new int[0], IntStream.of().toArray());
+    assertEquals(new int[] {1}, IntStream.of(1).toArray());
+    assertEquals(new int[] {3,2,0}, IntStream.of(3,2,0).toArray());
+  }
+
+  public void testReduce() {
+    int reduced = IntStream.of(1, 2, 4).reduce(0, Integer::sum);
+    assertEquals(7, reduced);
+
+    reduced = IntStream.of().reduce(0, Integer::sum);
+    assertEquals(0, reduced);
+
+    OptionalInt maybe = IntStream.of(1, 4, 8).reduce(Integer::sum);
+    assertTrue(maybe.isPresent());
+    assertEquals(13, maybe.getAsInt());
+    maybe = IntStream.of().reduce(Integer::sum);
+    assertFalse(maybe.isPresent());
+  }
+
+  public void testFilter() {
+    // unconsumed stream never runs filter
+    boolean[] data = {false};
+    IntStream.of(1, 2, 3).filter(i -> data[0] |= true);
+    assertFalse(data[0]);
+
+    // one result
+    assertEquals(
+        new int[] {1},
+        IntStream.of(1, 2, 3, 4, 3).filter(a -> a == 1).toArray()
+    );
+    // zero results
+    assertEquals(
+        new int[0],
+        IntStream.of(1, 2, 3, 4, 3).filter(a -> false).toArray()
+    );
+    // two results
+    assertEquals(
+        new int[] {2, 4},
+        IntStream.of(1, 2, 3, 4, 3).filter(a -> a % 2 == 0).toArray()
+    );
+    // all
+    assertEquals(
+        new int[] {1, 2, 3, 4, 3},
+        IntStream.of(1, 2, 3, 4, 3).filter(a -> true).toArray()
+    );
+  }
+
+  public void testMap() {
+    // unconsumed stream never runs map
+    int[] data = {0};
+    IntStream.of(1, 2, 3).map(i -> data[0]++);
+    assertEquals(0, data[0]);
+
+    assertEquals(
+        new int[] {2, 4, 6},
+        IntStream.of(1, 2, 3).map(i -> i * 2).toArray()
+    );
+  }
+
+  public void testPeek() {
+    // unconsumed stream never peeks
+    boolean[] data = {false};
+    IntStream.of(1, 2, 3).peek(i -> data[0] |= true);
+    assertFalse(data[0]);
+
+    // make sure we saw it all in order
+    int[] items = new int[] {1, 2, 3};
+    List<Integer> peeked = new ArrayList<>();
+    IntStream.of(items).peek(peeked::add).forEach(item -> {
+      // do nothing, just run
+    });
+    assertEquals(items.length, peeked.size());
+    for (int i = 0; i < items.length; i++) {
+      assertEquals(items[i], (int) peeked.get(i));
+    }
+  }
+
+  // same impl, no parallel in browser
+  public void testFindFirstOrAny() {
+    OptionalInt any = IntStream.of(1, 2).findAny();
+    assertTrue(any.isPresent());
+    assertEquals(1, any.getAsInt());
+  }
+
+  public void testAnyMatch() {
+    // all
+    assertTrue(IntStream.of(1, 2).anyMatch(s -> true));
+
+    // some
+    assertTrue(IntStream.of(1, 2).anyMatch(s -> s == 1));
+
+    // none
+    assertFalse(IntStream.of(1, 2).anyMatch(s -> false));
+  }
+
+  public void testAllMatch() {
+    // all
+    assertTrue(IntStream.of(1, 2).allMatch(s -> true));
+
+    // some
+    assertFalse(IntStream.of(1, 2).allMatch(s -> s == 1));
+
+    // none
+    assertFalse(IntStream.of(1, 2).allMatch(s -> false));
+  }
+
+  public void testNoneMatch() {
+    // all
+    assertFalse(IntStream.of(1, 2).noneMatch(s -> true));
+
+    // some
+    assertFalse(IntStream.of(1, 2).noneMatch(s -> s == 1));
+
+    // none
+    assertTrue(IntStream.of(1, 2).noneMatch(s -> false));
+  }
+
+  public void testFlatMap() {
+    assertEquals(0, IntStream.empty().flatMap(value -> IntStream.of(1)).count());
+    assertEquals(0, IntStream.of(1).flatMap(value -> IntStream.empty()).count());
+    assertEquals(0, IntStream.of(1).flatMap(value -> IntStream.of()).count());
+    assertEquals(0, IntStream.of().flatMap(value -> IntStream.of(1)).count());
+    assertEquals(1, IntStream.of(1).flatMap(value -> IntStream.of(1)).count());
+
+    IntStream values = IntStream.of(1, 2, 3);
+
+    assertEquals(
+        new int[] {1, 2, 2, 4, 3, 6},
+        values.flatMap(i -> IntStream.of(i, i * 2)).toArray()
+    );
+  }
+
+  public void testMapToOthers() {
+    Supplier<IntStream> s = () -> IntStream.of(1, 2, 10);
+
+    assertEquals(
+        new String[] {"1", "2", "10"},
+        s.get().mapToObj(String::valueOf).toArray(String[]::new)
+    );
+
+    assertEquals(
+        new long[] {1, 2, 10},
+        s.get().mapToLong(i -> (long) i).toArray()
+    );
+
+    assertEquals(
+        new double[] {1, 2, 10},
+        s.get().mapToDouble(i -> (double) i).toArray()
+    );
+  }
+
+  public void testDistinct() {
+    int[] distinct = IntStream.of(1, 2, 3, 2).distinct().toArray();
+    assertEquals(3, distinct.length);
+    assertEquals(1 + 2 + 3, distinct[0] + distinct[1] + distinct[2]);
+  }
+
+  public void testSorted() {
+    int[] sorted = IntStream.of(3, 1, 2).sorted().toArray();
+    assertEquals(new int[] {1, 2, 3}, sorted);
+  }
+
+  public void testMinMax() {
+    Supplier<IntStream> stream = () -> IntStream.of(2, 3, 4, 1);
+
+    assertEquals(1, stream.get().min().orElse(0));
+    assertEquals(4, stream.get().max().orElse(0));
+
+    assertFalse(stream.get().filter(a -> false).max().isPresent());
+    assertFalse(stream.get().filter(a -> false).min().isPresent());
+  }
+
+  public void testCountLimitSkip() {
+    Supplier<IntStream> stream = () -> IntStream.of(1, 2, 3, 4);
+
+    assertEquals(4, stream.get().count());
+
+    assertEquals(4, stream.get().limit(4).count());
+    assertEquals(4, stream.get().limit(5).count());
+    assertEquals(3, stream.get().limit(3).count());
+
+    assertEquals(3, stream.get().skip(1).limit(3).count());
+
+    assertEquals(2, stream.get().limit(3).skip(1).count());
+
+    assertEquals(1, stream.get().skip(3).count());
+
+    assertEquals(new int[] {3, 4}, stream.get().skip(2).limit(3).toArray());
+    assertEquals(new int[] {3}, stream.get().skip(2).limit(1).toArray());
+
+    assertEquals(new int[] {4}, stream.get().skip(3).toArray());
+    assertEquals(new int[] {}, stream.get().skip(5).toArray());
+
+    assertEquals(new int[] {1, 2}, stream.get().limit(2).toArray());
+
+    assertEquals(new int[] {2}, stream.get().limit(2).skip(1).toArray());
+  }
+
+  public void testBoxed() {
+    Supplier<IntStream> stream = () -> IntStream.of(1, 2);
+    Stream<Integer> expected = stream.get().mapToObj(Integer::valueOf);
+    assertEquals(expected.toArray(), stream.get().boxed().toArray());
+  }
+
+  public void testAsOtherPrimitive() {
+    Supplier<IntStream> stream = () -> IntStream.of(1, 2);
+
+    DoubleStream actualDoubleStream = stream.get().asDoubleStream();
+    assertEquals(new double[]{1, 2}, actualDoubleStream.toArray());
+
+    LongStream actualLongStream = stream.get().asLongStream();
+    assertEquals(new long[] {1, 2}, actualLongStream.toArray());
+  }
+
+  public void testSummaryStats() {
+    Supplier<IntStream> stream = () -> IntStream.of(1, 2, 3);
+    IntSummaryStatistics summaryStats = stream.get().summaryStatistics();
+    assertEquals(3, summaryStats.getCount());
+    assertEquals(1, summaryStats.getMin());
+    assertEquals(2, summaryStats.getAverage(), 0d);
+    assertEquals(3, summaryStats.getMax());
+    assertEquals(6, summaryStats.getSum());
+
+    summaryStats.accept(6);
+    assertEquals(4, summaryStats.getCount());
+    assertEquals(1, summaryStats.getMin());
+    assertEquals(3, summaryStats.getAverage(), 0d);
+    assertEquals(6, summaryStats.getMax());
+    assertEquals(12, summaryStats.getSum());
+
+    IntSummaryStatistics combinedSumStats = stream.get().summaryStatistics();
+    combinedSumStats.combine(IntStream.of(4, 5, 6, 0).summaryStatistics());
+    assertEquals(7, combinedSumStats.getCount());
+    assertEquals(0, combinedSumStats.getMin());
+    assertEquals(3, combinedSumStats.getAverage(), 0d);
+    assertEquals(6, combinedSumStats.getMax());
+    assertEquals(21, combinedSumStats.getSum());
+  }
+
+  public void testAverage() {
+    assertFalse(IntStream.empty().average().isPresent());
+    assertEquals(2.0d, IntStream.of(1, 2, 3).average().getAsDouble(), 0d);
+    assertEquals(0d, IntStream.of(1, 2, -3).average().getAsDouble(), 0d);
+    assertEquals(-2.0d, IntStream.of(-1, -2, -3).average().getAsDouble(), 0d);
+  }
+
+  public void testSum() {
+    assertEquals(6, IntStream.of(1, 2, 3).sum());
+    assertEquals(0, IntStream.of(1, 2, -3).sum());
+    assertEquals(-6, IntStream.of(-1, -2, -3).sum());
+  }
+
+  public void testCollect() {
+    String val = IntStream.of(1, 2, 3, 4, 5).collect(StringBuilder::new,
+        // TODO switch to a lambda reference once #9340 is fixed
+        (stringBuilder, i) -> stringBuilder.append(i),
+        StringBuilder::append).toString();
+
+    assertEquals("12345", val);
+  }
+
+  public void testForEach() {
+    List<Integer> vals = new ArrayList<>();
+    IntStream.of(1, 2, 3, 4, 5).forEach(vals::add);
+    assertEquals(5, vals.size());
+    assertEquals(new Integer[] {1, 2, 3, 4, 5}, vals.toArray(new Integer[vals.size()]));
+  }
+
+  public void testIterator() {
+    List<Integer> vals = new ArrayList<>();
+    Iterator<Integer> iterator = IntStream.of(1, 2, 3, 4, 5).iterator();
+    while (iterator.hasNext()) {
+      vals.add(iterator.next());
+    }
+    assertEquals(5, vals.size());
+    assertEquals(new Integer[] {1, 2, 3, 4, 5}, vals.toArray(new Integer[vals.size()]));
+  }
+
+  public void testSpliterator() {
+    Spliterator<Integer> spliterator = IntStream.of(1, 2, 3, 4, 5).spliterator();
+    assertEquals(5, spliterator.estimateSize());
+    assertEquals(5, spliterator.getExactSizeIfKnown());
+
+    List<Integer> vals = new ArrayList<>();
+    while (spliterator.tryAdvance(vals::add)) {
+      // work is all done in the condition
+    }
+
+    assertEquals(5, vals.size());
+    assertEquals(new Integer[] {1, 2, 3, 4, 5}, vals.toArray(new Integer[vals.size()]));
+  }
+}
diff --git a/user/test/com/google/gwt/emultest/java8/util/stream/LongStreamTest.java b/user/test/com/google/gwt/emultest/java8/util/stream/LongStreamTest.java
new file mode 100644
index 0000000..407f4bf
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java8/util/stream/LongStreamTest.java
@@ -0,0 +1,457 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.emultest.java8.util.stream;
+
+import com.google.gwt.emultest.java.util.EmulTestBase;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.LongSummaryStatistics;
+import java.util.OptionalLong;
+import java.util.Spliterator;
+import java.util.function.LongSupplier;
+import java.util.function.Supplier;
+import java.util.stream.DoubleStream;
+import java.util.stream.LongStream;
+import java.util.stream.Stream;
+
+/**
+ * Tests {@link LongStream}.
+ */
+public class LongStreamTest extends EmulTestBase {
+
+  public void testEmptyStream() {
+    LongStream empty = LongStream.empty();
+    assertEquals(0, empty.count());
+    try {
+      empty.count();
+      fail("second terminal operation should have thrown IllegalStateEx");
+    } catch (IllegalStateException expected) {
+      // expected
+    }
+
+    assertEquals(0, LongStream.empty().limit(2).toArray().length);
+    assertEquals(0L, LongStream.empty().count());
+    assertEquals(0L, LongStream.empty().limit(2).count());
+
+    assertFalse(LongStream.empty().findFirst().isPresent());
+    assertFalse(LongStream.empty().findAny().isPresent());
+    assertFalse(LongStream.empty().max().isPresent());
+    assertFalse(LongStream.empty().min().isPresent());
+    assertTrue(LongStream.empty().noneMatch(item -> true));
+    assertTrue(LongStream.empty().allMatch(item -> true));
+    assertFalse(LongStream.empty().anyMatch(item -> true));
+    assertEquals(new long[0], LongStream.empty().toArray());
+  }
+
+  public void testStreamOfOne() {
+    Supplier<LongStream> one = () -> LongStream.of(1);
+    assertEquals(new long[]{1L}, one.get().toArray());
+    assertEquals(1L, one.get().count());
+    assertEquals(1, one.get().findFirst().getAsLong());
+    assertEquals(1, one.get().findAny().getAsLong());
+  }
+
+  public void testBuilder() {
+    LongStream s = LongStream.builder()
+        .add(1L)
+        .add(3L)
+        .add(2L)
+        .build();
+
+    assertEquals(
+        new long[] {1L, 3L, 2L},
+        s.toArray()
+    );
+
+    LongStream.Builder builder = LongStream.builder();
+    LongStream built = builder.build();
+    assertEquals(0L, built.count());
+    try {
+      builder.build();
+      fail("build() after build() should fail");
+    } catch (IllegalStateException expected) {
+      // expected
+    }
+    try {
+      builder.add(10L);
+      fail("add() after build() should fail");
+    } catch (IllegalStateException expected) {
+      // expected
+    }
+  }
+
+  public void testConcat() {
+    Supplier<LongStream> adbc = () -> LongStream.concat(LongStream.of(1, 4), LongStream.of(2, 3));
+
+    assertEquals(new long[]{1L, 4L, 2L, 3L}, adbc.get().toArray());
+    assertEquals(new long[]{1L, 2L, 3L, 4L}, adbc.get().sorted().toArray());
+
+    List<String> closed = new ArrayList<>();
+    LongStream first = LongStream.of(1L).onClose(() -> closed.add("first"));
+    LongStream second = LongStream.of(2L).onClose(() -> closed.add("second"));
+
+    LongStream concat = LongStream.concat(first, second);
+
+    // read everything, make sure we saw it all and didn't close automatically
+    long collectedAll = concat.sum();
+    assertEquals(3L, collectedAll);
+    assertEquals(0, closed.size());
+
+    concat.close();
+    assertEquals(Arrays.asList("first", "second"), closed);
+  }
+
+  public void testIterate() {
+    assertEquals(
+        new long[]{10L, 11L, 12L, 13L, 14L},
+        LongStream.iterate(0L, l -> l + 1L)
+            .skip(10)
+            .limit(5)
+            .toArray()
+    );
+  }
+
+  public void testGenerate() {
+    // infinite, but if you limit it is already too short to skip much
+    assertEquals(new long[0], LongStream.generate(makeGenerator()).limit(4).skip(5).toArray());
+
+    assertEquals(
+        new long[]{10L, 11L, 12L, 13L, 14L},
+        LongStream.generate(makeGenerator())
+            .skip(10)
+            .limit(5)
+            .toArray()
+    );
+  }
+
+  private LongSupplier makeGenerator() {
+    return new LongSupplier() {
+      long next = 0L;
+
+      @Override
+      public long getAsLong() {
+        return next++;
+      }
+    };
+  }
+
+  public void testRange() {
+    assertEquals(new long[] {1L, 2L, 3L, 4L}, LongStream.range(1, 5).toArray());
+    assertEquals(new long[] {-1L, 0L, 1L, 2L, 3L, 4L}, LongStream.range(-1, 5).toArray());
+    assertEquals(new long[] {}, LongStream.range(1, -5).toArray());
+    assertEquals(new long[] {}, LongStream.range(-1, -5).toArray());
+  }
+
+  public void testRangeClosed() {
+    assertEquals(new long[] {1L, 2L, 3L, 4L, 5L}, LongStream.rangeClosed(1, 5).toArray());
+    assertEquals(new long[] {-1L, 0L, 1L, 2L, 3L, 4L, 5L}, LongStream.rangeClosed(-1, 5).toArray());
+    assertEquals(new long[] {}, LongStream.rangeClosed(1, -5).toArray());
+    assertEquals(new long[] {}, LongStream.rangeClosed(-1, -5).toArray());
+  }
+
+  public void testToArray() {
+    assertEquals(new long[0], LongStream.of().toArray());
+    assertEquals(new long[] {1L}, LongStream.of(1L).toArray());
+    assertEquals(new long[] {3L, 2L, 0L}, LongStream.of(3L,2L,0L).toArray());
+  }
+
+  public void testReduce() {
+    long reduced = LongStream.of(1L, 2L, 4L).reduce(0, Long::sum);
+    assertEquals(7, reduced);
+
+    reduced = LongStream.of().reduce(0, Long::sum);
+    assertEquals(0L, reduced);
+
+    OptionalLong maybe = LongStream.of(1L, 4L, 8L).reduce(Long::sum);
+    assertTrue(maybe.isPresent());
+    assertEquals(13L, maybe.getAsLong());
+    maybe = LongStream.of().reduce(Long::sum);
+    assertFalse(maybe.isPresent());
+  }
+
+  public void testFilter() {
+    // unconsumed stream never runs filter
+    boolean[] data = {false};
+    LongStream.of(1L, 2L, 3L).filter(i -> data[0] |= true);
+    assertFalse(data[0]);
+
+    // one result
+    assertEquals(
+        new long[] {1L},
+        LongStream.of(1L, 2L, 3L, 4L, 3L).filter(a -> a == 1).toArray()
+    );
+    // zero results
+    assertEquals(
+        new long[0],
+        LongStream.of(1L, 2L, 3L, 4L, 3L).filter(a -> false).toArray()
+    );
+    // two results
+    assertEquals(
+        new long[] {2L, 4L},
+        LongStream.of(1L, 2L, 3L, 4L, 3L).filter(a -> a % 2 == 0).toArray()
+    );
+    // all
+    assertEquals(
+        new long[] {1L, 2L, 3L, 4L, 3L},
+        LongStream.of(1L, 2L, 3L, 4L, 3L).filter(a -> true).toArray()
+    );
+  }
+
+  public void testMap() {
+    // unconsumed stream never runs map
+    int[] data = {0};
+    LongStream.of(1L, 2L, 3L).map(i -> data[0]++);
+    assertEquals(0, data[0]);
+
+    assertEquals(
+        new long[] {2L, 4L, 6L},
+        LongStream.of(1L, 2L, 3L).map(i -> i * 2).toArray()
+    );
+  }
+
+  public void testPeek() {
+    // unconsumed stream never peeks
+    boolean[] data = {false};
+    LongStream.of(1L, 2L, 3L).peek(i -> data[0] |= true);
+    assertFalse(data[0]);
+
+    // make sure we saw it all in order
+    long[] items = new long[] {1L, 2L, 3L};
+    List<Long> peeked = new ArrayList<>();
+    LongStream.of(items).peek(peeked::add).forEach(item -> {
+      // do nothing, just run
+    });
+    assertEquals(items.length, peeked.size());
+    for (int i = 0; i < items.length; i++) {
+      assertEquals(items[i], (long) peeked.get(i));
+    }
+  }
+
+  // same impl, no parallel in browser
+  public void testFindFirstOrAny() {
+    OptionalLong any = LongStream.of(1L, 2L).findAny();
+    assertTrue(any.isPresent());
+    assertEquals(1L, any.getAsLong());
+  }
+
+  public void testAnyMatch() {
+    // all
+    assertTrue(LongStream.of(1L, 2L).anyMatch(s -> true));
+
+    // some
+    assertTrue(LongStream.of(1L, 2L).anyMatch(s -> s == 1L));
+
+    // none
+    assertFalse(LongStream.of(1L, 2L).anyMatch(s -> false));
+  }
+
+  public void testAllMatch() {
+    // all
+    assertTrue(LongStream.of(1L, 2L).allMatch(s -> true));
+
+    // some
+    assertFalse(LongStream.of(1L, 2L).allMatch(s -> s == 1L));
+
+    // none
+    assertFalse(LongStream.of(1L, 2L).allMatch(s -> false));
+  }
+
+  public void testNoneMatch() {
+    // all
+    assertFalse(LongStream.of(1L, 2L).noneMatch(s -> true));
+
+    // some
+    assertFalse(LongStream.of(1L, 2L).noneMatch(s -> s == 1L));
+
+    // none
+    assertTrue(LongStream.of(1L, 2L).noneMatch(s -> false));
+  }
+
+  public void testFlatMap() {
+    assertEquals(0L, LongStream.empty().flatMap(value -> LongStream.of(1L)).count());
+    assertEquals(0L, LongStream.of(1L).flatMap(value -> LongStream.empty()).count());
+    assertEquals(0L, LongStream.of(1L).flatMap(value -> LongStream.of()).count());
+    assertEquals(0L, LongStream.of().flatMap(value -> LongStream.of(1L)).count());
+    assertEquals(1L, LongStream.of(1L).flatMap(value -> LongStream.of(1L)).count());
+
+    LongStream values = LongStream.of(1L, 2L, 3L);
+
+    assertEquals(
+        new long[] {1L, 2L, 2L, 4L, 3L, 6L},
+        values.flatMap(i -> LongStream.of(i, i * 2)).toArray()
+    );
+  }
+
+  public void testMapToOthers() {
+    Supplier<LongStream> s = () -> LongStream.of(1, 2, 10);
+
+    assertEquals(
+        new String[] {"1", "2", "10"},
+        s.get().mapToObj(String::valueOf).toArray(String[]::new)
+    );
+
+    assertEquals(
+        new int[] {1, 2, 10},
+        s.get().mapToInt(i -> (int) i).toArray()
+    );
+
+    assertEquals(
+        new double[] {1d, 2d, 10d},
+        s.get().mapToDouble(i -> (double) i).toArray()
+    );
+  }
+
+  public void testDistinct() {
+    long[] distinct = LongStream.of(1L, 2L, 3L, 2L).distinct().toArray();
+    assertEquals(3, distinct.length);
+    assertEquals(1L + 2L + 3L, distinct[0] + distinct[1] + distinct[2]);
+  }
+
+  public void testSorted() {
+    long[] sorted = LongStream.of(3L, 1L, 2L).sorted().toArray();
+    assertEquals(new long[] {1L, 2L, 3L}, sorted);
+  }
+
+  public void testMinMax() {
+    Supplier<LongStream> stream = () -> LongStream.of(2L, 3L, 4L, 1L);
+
+    assertEquals(1L, stream.get().min().orElse(0));
+    assertEquals(4L, stream.get().max().orElse(0));
+
+    assertFalse(stream.get().filter(a -> false).max().isPresent());
+    assertFalse(stream.get().filter(a -> false).min().isPresent());
+  }
+
+  public void testCountLimitSkip() {
+    Supplier<LongStream> stream = () -> LongStream.of(1L, 2L, 3L, 4L);
+
+    assertEquals(4L, stream.get().count());
+
+    assertEquals(4L, stream.get().limit(4).count());
+    assertEquals(4L, stream.get().limit(5).count());
+    assertEquals(3L, stream.get().limit(3).count());
+
+    assertEquals(3L, stream.get().skip(1).limit(3).count());
+
+    assertEquals(2L, stream.get().limit(3).skip(1).count());
+
+    assertEquals(1L, stream.get().skip(3).count());
+
+    assertEquals(new long[] {3L, 4L}, stream.get().skip(2).limit(3).toArray());
+    assertEquals(new long[] {3L}, stream.get().skip(2).limit(1).toArray());
+
+    assertEquals(new long[] {4L}, stream.get().skip(3).toArray());
+    assertEquals(new long[] {}, stream.get().skip(5).toArray());
+
+    assertEquals(new long[] {1L, 2L}, stream.get().limit(2).toArray());
+
+    assertEquals(new long[] {2L}, stream.get().limit(2).skip(1).toArray());
+  }
+
+  public void testBoxed() {
+    Supplier<LongStream> stream = () -> LongStream.of(1L, 2L);
+    Stream<Long> expected = stream.get().mapToObj(Long::valueOf);
+    assertEquals(expected.toArray(), stream.get().boxed().toArray());
+  }
+
+  public void testAsOtherPrimitive() {
+    Supplier<LongStream> stream = () -> LongStream.of(1L, 2L);
+    DoubleStream actualDoubleStream = stream.get().asDoubleStream();
+    assertEquals(new double[]{1, 2}, actualDoubleStream.toArray());
+  }
+
+  public void testSummaryStats() {
+    Supplier<LongStream> stream = () -> LongStream.of(1L, 2L, 3L);
+    LongSummaryStatistics summaryStats = stream.get().summaryStatistics();
+    assertEquals(3L, summaryStats.getCount());
+    assertEquals(1L, summaryStats.getMin());
+    assertEquals(2L, summaryStats.getAverage(), 0d);
+    assertEquals(3L, summaryStats.getMax());
+    assertEquals(6L, summaryStats.getSum());
+
+    summaryStats.accept(6L);
+    assertEquals(4L, summaryStats.getCount());
+    assertEquals(1L, summaryStats.getMin());
+    assertEquals(3L, summaryStats.getAverage(), 0d);
+    assertEquals(6L, summaryStats.getMax());
+    assertEquals(12L, summaryStats.getSum());
+
+    LongSummaryStatistics combinedSumStats = stream.get().summaryStatistics();
+    combinedSumStats.combine(LongStream.of(4L, 5L, 6L, 0L).summaryStatistics());
+    assertEquals(7L, combinedSumStats.getCount());
+    assertEquals(0L, combinedSumStats.getMin());
+    assertEquals(3L, combinedSumStats.getAverage(), 0d);
+    assertEquals(6L, combinedSumStats.getMax());
+    assertEquals(21L, combinedSumStats.getSum());
+  }
+
+  public void testAverage() {
+    assertFalse(LongStream.empty().average().isPresent());
+    assertEquals(2.0d, LongStream.of(1L, 2L, 3L).average().getAsDouble(), 0d);
+    assertEquals(0d, LongStream.of(1L, 2L, -3L).average().getAsDouble(), 0d);
+    assertEquals(-2.0d, LongStream.of(-1L, -2L, -3L).average().getAsDouble(), 0d);
+  }
+
+  public void testSum() {
+    assertEquals(6L, LongStream.of(1L, 2L, 3L).sum());
+    assertEquals(0L, LongStream.of(1L, 2L, -3L).sum());
+    assertEquals(-6L, LongStream.of(-1L, -2L, -3L).sum());
+  }
+
+  public void testCollect() {
+    String val = LongStream.of(1L, 2L, 3L, 4L, 5L).collect(StringBuilder::new,
+        // TODO switch to a lambda reference once #9340 is fixed
+        (stringBuilder, lng) -> stringBuilder.append(lng),
+        StringBuilder::append).toString();
+
+    assertEquals("12345", val);
+  }
+
+  public void testForEach() {
+    List<Long> vals = new ArrayList<>();
+    LongStream.of(1L, 2L, 3L, 4L, 5L).forEach(vals::add);
+    assertEquals(5, vals.size());
+    assertEquals(new Long[] {1L, 2L, 3L, 4L, 5L}, vals.toArray(new Long[vals.size()]));
+  }
+
+  public void testIterator() {
+    List<Long> vals = new ArrayList<>();
+    Iterator<Long> iterator = LongStream.of(1L, 2L, 3L, 4L, 5L).iterator();
+    while (iterator.hasNext()) {
+      vals.add(iterator.next());
+    }
+    assertEquals(5, vals.size());
+    assertEquals(new Long[] {1L, 2L, 3L, 4L, 5L}, vals.toArray(new Long[vals.size()]));
+  }
+
+  public void testSpliterator() {
+    Spliterator<Long> spliterator = LongStream.of(1L, 2L, 3L, 4L, 5L).spliterator();
+    assertEquals(5, spliterator.estimateSize());
+    assertEquals(5, spliterator.getExactSizeIfKnown());
+
+    List<Long> vals = new ArrayList<>();
+    while (spliterator.tryAdvance(vals::add)) {
+      // work is all done in the condition
+    }
+
+    assertEquals(5, vals.size());
+    assertEquals(new Long[] {1L, 2L, 3L, 4L, 5L}, vals.toArray(new Long[vals.size()]));
+  }
+}
diff --git a/user/test/com/google/gwt/emultest/java8/util/stream/StreamSupportTest.java b/user/test/com/google/gwt/emultest/java8/util/stream/StreamSupportTest.java
new file mode 100644
index 0000000..0ff6331
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java8/util/stream/StreamSupportTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.emultest.java8.util.stream;
+
+import static java.util.stream.StreamSupport.doubleStream;
+import static java.util.stream.StreamSupport.intStream;
+import static java.util.stream.StreamSupport.longStream;
+import static java.util.stream.StreamSupport.stream;
+
+import com.google.gwt.emultest.java.util.EmulTestBase;
+
+import java.util.Spliterators;
+import java.util.stream.DoubleStream;
+import java.util.stream.IntStream;
+import java.util.stream.LongStream;
+import java.util.stream.Stream;
+
+/**
+ * Tests {@link java.util.stream.StreamSupport}.
+ */
+public class StreamSupportTest extends EmulTestBase {
+
+  public void testDoubleStream() {
+    DoubleStream doubles = doubleStream(
+        Spliterators.spliterator(new double[] {1d, 2d, 3d, 4d}, 0),
+        false
+    );
+
+    assertNotNull(doubles);
+    assertEquals(new double[]{1d, 2d, 3d}, doubles.limit(3).toArray());
+
+    doubles = doubleStream(() -> Spliterators.spliterator(new double[] {1d, 2d, 3d, 4d}, 0), 0,
+        false);
+
+    assertNotNull(doubles);
+    assertEquals(
+        new double[] {2d, 3d},
+        doubles.skip(1).limit(2).toArray()
+    );
+  }
+
+  public void testIntStream() {
+    IntStream ints = intStream(
+        Spliterators.spliterator(new int[] {1, 2, 3, 4}, 0),
+        false
+    );
+
+    assertNotNull(ints);
+    assertEquals(new int[] {1, 2, 3}, ints.limit(3).toArray());
+
+    ints = intStream(() -> Spliterators.spliterator(new int[] {1, 2, 3, 4}, 0), 0, false);
+
+    assertNotNull(ints);
+    assertEquals(
+        new int[] {2, 3},
+        ints.skip(1).limit(2).toArray()
+    );
+  }
+
+  public void testLongStream() {
+    LongStream longs = longStream(
+        Spliterators.spliterator(new long[] {1L, 2L, 3L, 4L}, 0),
+        false
+    );
+
+    assertNotNull(longs);
+    assertEquals(new long[] {1L, 2L, 3L}, longs.limit(3).toArray());
+
+    longs = longStream(() -> Spliterators.spliterator(new long[] {1L, 2L, 3L, 4L}, 0), 0, false);
+
+    assertNotNull(longs);
+    assertEquals(
+        new long[] {2L, 3L},
+        longs.skip(1).limit(2).toArray()
+    );
+  }
+
+  public void testStream() {
+    Stream<String> strings = stream(
+        Spliterators.spliterator(new String[] {"a", "b", "c", "d"}, 0),
+        false
+    );
+
+    assertNotNull(strings);
+    assertEquals(new String[] {"a", "b", "c"}, strings.limit(3).toArray());
+
+    strings = stream(() -> Spliterators.spliterator(new String[] {"a", "b", "c", "d"}, 0), 0, false);
+
+    assertNotNull(strings);
+    assertEquals(
+        new String[] {"b", "c"},
+        strings.skip(1).limit(2).toArray()
+    );
+  }
+}
diff --git a/user/test/com/google/gwt/emultest/java8/util/stream/StreamTest.java b/user/test/com/google/gwt/emultest/java8/util/stream/StreamTest.java
new file mode 100644
index 0000000..d46bfaf
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java8/util/stream/StreamTest.java
@@ -0,0 +1,627 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.google.gwt.emultest.java8.util.stream;
+
+import static java.util.Arrays.asList;
+
+import com.google.gwt.emultest.java.util.EmulTestBase;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Optional;
+import java.util.Spliterator;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.DoubleStream;
+import java.util.stream.IntStream;
+import java.util.stream.LongStream;
+import java.util.stream.Stream;
+
+/**
+ * Tests {@link Stream}.
+ */
+public class StreamTest extends EmulTestBase {
+
+  public void testEmptyStream() {
+    Stream<Object> empty = Stream.empty();
+    assertEquals(0, empty.count());
+    try {
+      empty.count();
+      fail("second terminal operation should have thrown IllegalStateEx");
+    } catch (IllegalStateException expected) {
+      // expected
+    }
+
+    assertEquals(0, Stream.empty().limit(2).collect(Collectors.toList()).size());
+    assertEquals(0, Stream.empty().count());
+    assertEquals(0, Stream.empty().limit(2).count());
+
+    assertFalse(Stream.empty().findFirst().isPresent());
+    assertFalse(Stream.empty().findAny().isPresent());
+    assertFalse(Stream.<String>empty().max(Comparator.naturalOrder()).isPresent());
+    assertFalse(Stream.<String>empty().min(Comparator.naturalOrder()).isPresent());
+    assertTrue(Stream.empty().allMatch(item -> true));
+    assertFalse(Stream.empty().anyMatch(item -> true));
+    assertTrue(Stream.empty().noneMatch(item -> false));
+    assertFalse(Stream.empty().iterator().hasNext());
+    assertFalse(Stream.empty().spliterator().tryAdvance(a -> fail("should not advance")));
+    Stream.empty().spliterator().forEachRemaining(a -> fail("should not advance"));
+    assertEquals(new Object[0], Stream.empty().toArray());
+    assertEquals(new Object[0], Stream.empty().toArray(Object[]::new));
+  }
+
+  public void testStreamOfOne() {
+    Supplier<Stream<String>> one = () -> Stream.of("");
+    assertEquals(Collections.singletonList(""), one.get().collect(Collectors.toList()));
+    assertEquals(1L, one.get().count());
+    assertEquals("", one.get().findFirst().get());
+    assertEquals("", one.get().findAny().get());
+  }
+
+  public void testBuilder() {
+    Supplier<Stream<String>> s = () -> Stream.<String>builder()
+        .add("1")
+        .add("3")
+        .add("2")
+        .build();
+
+    Optional<String> max = s.get().filter(str -> !str.equals("3")).max(Comparator.naturalOrder());
+    assertTrue(max.isPresent());
+    assertEquals("2", max.get());
+
+    max = s.get().max(Comparator.reverseOrder());
+    assertTrue(max.isPresent());
+    assertEquals("1", max.get());
+
+    Stream.Builder<Object> builder = Stream.builder();
+    Stream<Object> built = builder.build();
+    assertEquals(0, built.count());
+    try {
+      builder.build();
+      fail("build() after build() should fail");
+    } catch (IllegalStateException expected) {
+      // expected
+    }
+    try {
+      builder.add("asdf");
+      fail("add() after build() should fail");
+    } catch (IllegalStateException expected) {
+      // expected
+    }
+  }
+
+  public void testConcat() {
+    Supplier<Stream<String>> adbc = () -> Stream.concat(Stream.of("a", "d"), Stream.of("b", "c"));
+
+    assertEquals(new String[]{"a", "d", "b", "c"}, adbc.get().toArray(String[]::new));
+    assertEquals(new String[]{"a", "b", "c", "d"}, adbc.get().sorted().toArray(String[]::new));
+
+    List<String> closed = new ArrayList<>();
+    Stream<String> first = Stream.of("first").onClose(() -> closed.add("first"));
+    Stream<String> second = Stream.of("second").onClose(() -> closed.add("second"));
+
+    Stream<String> concat = Stream.concat(first, second);
+
+    // read everything, make sure we saw it all and didn't close automatically
+    String collectedAll = concat.collect(Collectors.joining());
+    assertEquals("firstsecond", collectedAll);
+    assertEquals(0, closed.size());
+
+    concat.close();
+    assertEquals(Arrays.asList("first", "second"), closed);
+  }
+
+  public void testIterate() {
+    assertEquals(
+        new Integer[]{10, 11, 12, 13, 14},
+        Stream.iterate(0, i -> i + 1)
+            .skip(10)
+            .limit(5)
+            .toArray(Integer[]::new)
+    );
+  }
+
+  public void testGenerate() {
+    // infinite, but if you limit it is already too short to skip much
+    assertEquals(new Integer[]{}, Stream.generate(makeGenerator())
+        .limit(4)
+        .skip(5)
+        .toArray(Integer[]::new));
+
+    assertEquals(new Integer[]{10, 11, 12, 13, 14}, Stream.generate(makeGenerator())
+        .skip(10)
+        .limit(5)
+        .toArray(Integer[]::new));
+  }
+
+  private Supplier<Integer> makeGenerator() {
+    return new Supplier<Integer>() {
+      int next = 0;
+
+      @Override
+      public Integer get() {
+        return next++;
+      }
+    };
+  }
+
+  public void testSpliterator() {
+    final String[] values = new String[] {"a", "b", "c"};
+
+    Spliterator<String> spliterator = Stream.of(values).spliterator();
+    assertEquals(3, spliterator.estimateSize());
+    assertEquals(3, spliterator.getExactSizeIfKnown());
+
+    List<String> actualValues = new ArrayList<>();
+    while (spliterator.tryAdvance(actualValues::add)) {
+      // work is all done in the condition
+    }
+
+    assertEquals(asList(values), actualValues);
+  }
+
+  public void testIterator() {
+    final String[] values = new String[] {"a", "b", "c"};
+
+    List<String> actualValues = new ArrayList<String>();
+    Iterator<String> iterator = Stream.of(values).iterator();
+    while (iterator.hasNext()) {
+      actualValues.add(iterator.next());
+    }
+    assertEquals(asList(values), actualValues);
+  }
+
+  public void testForEach() {
+    final String[] values = new String[] {"a", "b", "c"};
+
+    List<String> actualValues = new ArrayList<>();
+    Stream.of(values).forEach(actualValues::add);
+    assertEquals(asList(values), actualValues);
+  }
+
+  // toArray
+  public void testToArray() {
+    assertEquals(
+        new Object[]{"a", "b"},
+        asList("a", "b").stream().toArray()
+    );
+    assertEquals(
+        new String[]{"a", "b"},
+        asList("a", "b").stream().toArray(String[]::new)
+    );
+  }
+
+  // reduce
+  public void testReduce() {
+    String reduced = Stream.of("a", "b", "c").reduce("", String::concat);
+    assertEquals("abc", reduced);
+
+    reduced = Stream.<String>of().reduce("initial", String::concat);
+    assertEquals("initial", reduced);
+
+    Optional<String> maybe = Stream.of("a", "b", "c").reduce(String::concat);
+    assertTrue(maybe.isPresent());
+    assertEquals("abc", maybe.get());
+    maybe = Stream.<String>of().reduce(String::concat);
+    assertFalse(maybe.isPresent());
+
+    reduced = Stream.of("a", "b", "c").reduce("", String::concat, String::concat);
+    assertEquals("abc", reduced);
+  }
+
+  public void testCollect() {
+    final String[] values = new String[] {"a", "b", "c"};
+
+    String collectedString = Stream.of(values).collect(StringBuilder::new,
+        StringBuilder::append,
+        StringBuilder::append).toString();
+    assertEquals("abc", collectedString);
+
+    List<String> collectedList = Stream.of(values).collect(Collectors.toList());
+    assertEquals(asList(values), collectedList);
+  }
+
+  public void testFilter() {
+    // unconsumed stream never runs filter
+    boolean[] data = {false};
+    Stream.of(1, 2, 3).filter(i -> data[0] |= true);
+    assertFalse(data[0]);
+
+    // one result
+    assertEquals(
+        Collections.singletonList("a"),
+        Stream.of("a", "b", "c", "d", "c").filter(a -> a.equals("a")).collect(Collectors.toList())
+    );
+    // zero results
+    assertEquals(
+        Collections.emptyList(),
+        Stream.of("a", "b", "c", "d", "c").filter(a -> false).collect(Collectors.toList())
+    );
+    // two results
+    assertEquals(
+        asList("c3", "c5"),
+        Stream.of("a1", "b2", "c3", "d4", "c5")
+            .filter(a -> a.startsWith("c"))
+            .collect(Collectors.toList())
+    );
+    // all
+    assertEquals(
+        asList("a", "b", "c", "d", "c"),
+        Stream.of("a", "b", "c", "d", "c").filter(a -> true).collect(Collectors.toList())
+    );
+  }
+
+  public void testMap() {
+    // unconsumed stream never runs map
+    boolean[] data = {false};
+    Stream.of(1, 2, 3).map(i -> data[0] |= true);
+    assertFalse(data[0]);
+
+    assertEquals(
+        asList("#1", "#2", "#3"),
+        Stream.of(1, 2, 3).map(i -> "#" + i).collect(Collectors.toList())
+    );
+  }
+
+  public void testPeek() {
+    // unconsumed stream never peeks
+    boolean[] data = {false};
+    Stream.of(1, 2, 3).peek(i -> data[0] |= true);
+    assertFalse(data[0]);
+
+    // make sure we saw it all in order
+    List<String> items = asList("a", "b", "c");
+    List<String> peeked = new ArrayList<>();
+    items.stream().peek(peeked::add).forEach(item -> {
+      // deliberately do nothing, just run
+    });
+    assertEquals(items, peeked);
+  }
+
+  // same impl, no parallel in browser
+  public void testFindFirstOrAny() {
+    Optional<String> any = Stream.of("a", "b").findAny();
+    assertTrue(any.isPresent());
+    assertEquals("a", any.get());
+  }
+
+  public void testAnyMatch() {
+    // all
+    assertTrue(Stream.of("a", "b").anyMatch(s -> true));
+
+    // some
+    assertTrue(Stream.of("a", "b").anyMatch(s -> s.equals("a")));
+
+    // none
+    assertFalse(Stream.of("a", "b").anyMatch(s -> false));
+  }
+
+  public void testAllMatch() {
+    // all
+    assertTrue(Stream.of("a", "b").allMatch(s -> true));
+
+    // some
+    assertFalse(Stream.of("a", "b").allMatch(s -> s.equals("a")));
+
+    // none
+    assertFalse(Stream.of("a", "b").allMatch(s -> false));
+  }
+
+  public void testNoneMatch() {
+    // all
+    assertFalse(Stream.of("a", "b").noneMatch(s -> true));
+
+    // some
+    assertFalse(Stream.of("a", "b").noneMatch(s -> s.equals("a")));
+
+    // none
+    assertTrue(Stream.of("a", "b").noneMatch(s -> false));
+  }
+
+  public void testFlatMap() {
+    assertEquals(0, Stream.<Stream<String>>empty().flatMap(Function.identity()).count());
+    assertEquals(0, Stream.of(Stream.<String>empty()).flatMap(Function.identity()).count());
+    assertEquals(0, Stream.of(Stream.of()).flatMap(Function.identity()).count());
+    assertEquals(1, Stream.of(Stream.of("")).flatMap(Function.identity()).count());
+
+    Stream<Stream<String>> strings = Stream.of(Stream.of("a", "b"), Stream.empty(), Stream.of("c"));
+
+    assertEquals(
+        asList("a", "b", "c"),
+        strings.flatMap(Function.identity()).collect(Collectors.toList())
+    );
+  }
+  public void testMapToPrimitives() {
+    Supplier<Stream<String>> s = () -> Stream.of("1", "2", "10");
+
+    assertEquals(
+        new int[]{1, 2, 10},
+        s.get().mapToInt(Integer::parseInt).toArray()
+    );
+
+    assertEquals(
+        new long[]{1, 2, 10},
+        s.get().mapToLong(Long::parseLong).toArray()
+    );
+
+    assertEquals(
+        new double[]{1, 2, 10},
+        s.get().mapToDouble(Double::parseDouble).toArray()
+    );
+  }
+
+  public void testFlatMapToPrimitives() {
+    assertEquals(0, Stream.<IntStream>empty().flatMapToInt(Function.identity()).count());
+    assertEquals(0, Stream.of(IntStream.empty()).flatMapToInt(Function.identity()).count());
+    assertEquals(0, Stream.of(IntStream.of()).flatMapToInt(Function.identity()).count());
+    assertEquals(1, Stream.of(IntStream.of(0)).flatMapToInt(Function.identity()).count());
+
+    Stream<IntStream> intStreams = Stream.of(
+        IntStream.of(1, 2),
+        IntStream.empty(),
+        IntStream.of(5)
+    );
+    assertEquals(
+        new int[]{1, 2, 5},
+        intStreams.flatMapToInt(Function.identity()).toArray()
+    );
+
+    Stream<LongStream> longStreams = Stream.of(
+        LongStream.of(1, 2),
+        LongStream.empty(),
+        LongStream.of(5)
+    );
+    assertEquals(
+        new long[]{1, 2, 5},
+        longStreams.flatMapToLong(Function.identity()).toArray()
+    );
+
+    Stream<DoubleStream> doubleStreams = Stream.of(
+        DoubleStream.of(1, 2),
+        DoubleStream.empty(),
+        DoubleStream.of(5)
+    );
+    assertEquals(
+        new double[]{1, 2, 5},
+        doubleStreams.flatMapToDouble(Function.identity()).toArray()
+    );
+  }
+
+  public void testDistinct() {
+    List<String> distinct = asList("a", "b", "c", "b").stream()
+        .distinct()
+        .collect(Collectors.toList());
+    assertEquals(3, distinct.size());
+    assertTrue(distinct.contains("a"));
+    assertTrue(distinct.contains("b"));
+    assertTrue(distinct.contains("c"));
+  }
+
+  public void testSorted() {
+    List<String> sorted = asList("c", "a", "b").stream().sorted().collect(Collectors.toList());
+    List<String> reversed = asList("c", "a", "b").stream()
+        .sorted(Comparator.reverseOrder())
+        .collect(Collectors.toList());
+
+    assertEquals(asList("a", "b", "c"), sorted);
+    assertEquals(asList("c", "b", "a"), reversed);
+  }
+
+  public void testMinMax() {
+    Supplier<Stream<String>> stream = () -> Stream.of("b", "c", "d", "a");
+
+    assertEquals("a", stream.get().min(Comparator.naturalOrder()).orElse(null));
+    assertEquals("d", stream.get().min(Comparator.reverseOrder()).orElse(null));
+    assertEquals("a", stream.get().max(Comparator.reverseOrder()).orElse(null));
+    assertEquals("d", stream.get().max(Comparator.naturalOrder()).orElse(null));
+
+    assertFalse(stream.get().filter(a -> false).max(Comparator.naturalOrder()).isPresent());
+    assertFalse(stream.get().filter(a -> false).min(Comparator.naturalOrder()).isPresent());
+  }
+
+  public void testCountLimitSkip() {
+    Supplier<Stream<String>> stream = () -> asList("a", "b", "c", "d").stream();
+
+    assertEquals(4, stream.get().count());
+
+    assertEquals(4, stream.get().limit(4).count());
+    assertEquals(4, stream.get().limit(5).count());
+    assertEquals(3, stream.get().limit(3).count());
+
+    assertEquals(3, stream.get().skip(1).limit(3).count());
+
+    assertEquals(2, stream.get().limit(3).skip(1).count());
+
+    assertEquals(1, stream.get().skip(3).count());
+
+    assertEquals(asList("c", "d"), stream.get().skip(2).limit(3).collect(Collectors.toList()));
+    assertEquals(Collections.singletonList("c"), stream.get()
+        .skip(2)
+        .limit(1)
+        .collect(Collectors.toList()));
+
+    assertEquals(Collections.singletonList("d"), stream.get()
+        .skip(3)
+        .collect(Collectors.toList()));
+    assertEquals(Collections.emptyList(), stream.get()
+        .skip(5)
+        .collect(Collectors.toList()));
+
+    assertEquals(asList("a", "b"), stream.get()
+        .limit(2)
+        .collect(Collectors.toList()));
+
+    assertEquals(Collections.singletonList("b"), stream.get()
+        .limit(2)
+        .skip(1)
+        .collect(Collectors.toList()));
+  }
+
+  // This frustrating test was written first on the JVM stream to discover the basic behavior before
+  // trying to implement it in GWT. As far as I can tell, none of this is clearly described in
+  // javadoc. Also note that it is *not* required to use the returned stream from calling onClose
+  public void testCloseQuirks() {
+    // all subclasses use the same close()/onClose(...) impl, just test once with Stream.empty()
+
+    Stream<Object> s = Stream.of(1);
+    s.close();
+    // allow multiple close
+    s.close();
+
+    // Add a handler, close, and attempt to re-close - handler only runs the one time
+    int[] calledCount = {0};
+    s = Stream.empty();
+    s.onClose(() -> calledCount[0]++);
+    // shouldn't have been called yet
+    assertEquals(0, calledCount[0]);
+    s.close();
+    // called once
+    assertEquals(1, calledCount[0]);
+    s.close();
+    // not called again on subsequent closes
+    assertEquals(1, calledCount[0]);
+
+    // Add a handler after close, and re-close, the handler will only go off after the _second_
+    // close
+    calledCount[0] = 0;
+    s = Stream.of(1);
+    s.close();
+    s = s.onClose(() -> calledCount[0]++);
+    // shouldn't have been called yet
+    assertEquals(0, calledCount[0]);
+    s.close();
+    // frustratingly, the JVM apparently permits each handler when added to let the stream be closed
+    // _again_
+    assertEquals(1, calledCount[0]);
+
+    // Adding yet another runnable and closing again demonstrates this - only the new one is run,
+    // the old ones are not
+    s = s.onClose(() -> calledCount[0]++);
+    s.close();
+    assertEquals(2, calledCount[0]);
+
+    // Add two handlers, ensure both are called, and neither called the second time the stream is
+    // closed
+    calledCount[0] = 0;
+    s = Stream.empty();
+    s = s.onClose(() -> calledCount[0]++);
+    s = s.onClose(() -> calledCount[0]++);
+    s.close();
+    assertEquals(2, calledCount[0]);
+    s.close();
+    assertEquals(2, calledCount[0]);
+  }
+
+  public void testClose() {
+    // terminate stream before closing, confirm that handler is called
+    Stream<Object> s = Stream.of("a", "b", "c");
+    int[] calledCount = {0};
+    s = s.onClose(() -> calledCount[0]++);
+
+    long count = s.count();
+    assertEquals(3, count);
+    assertEquals(0, calledCount[0]);
+
+    s.close();
+    assertEquals(1, calledCount[0]);
+
+    // terminate stream after closing, confirm that handler is called, and terminating fails
+    s = Stream.of("a", "b", "c");
+    calledCount[0] = 0;
+    s = s.onClose(() -> calledCount[0]++);
+
+    s.close();
+    assertEquals(1, calledCount[0]);
+
+    try {
+      s.count();
+      fail("Expected IllegalStateException");
+    } catch (IllegalStateException expected) {
+      // expected
+    }
+    assertEquals(1, calledCount[0]);
+  }
+
+  public void testCloseException() {
+    // Try a single exception, confirm we catch it
+    Stream<Object> s = Stream.of(1, 2, 3);
+
+    RuntimeException a = new RuntimeException("a");
+    s.onClose(() -> {
+      throw a;
+    });
+    try {
+      s.close();
+      fail("RuntimeException expected");
+    } catch (RuntimeException expected) {
+      assertSame(a, expected);
+      assertEquals(0, expected.getSuppressed().length);
+    }
+
+    // Throw an exception in two of the three handlers, confirm both arrive and the third was called
+    // correctly
+    s = Stream.of(1, 2, 3);
+
+    RuntimeException a2 = new RuntimeException("a");
+    IllegalStateException b = new IllegalStateException("b");
+    int[] calledCount = {0};
+    s
+        .onClose(() -> {
+          throw a2;
+        })
+        .onClose(() -> {
+          throw b;
+        })
+        .onClose(() -> calledCount[0]++);
+
+    try {
+      s.close();
+      fail("RuntimeException expected");
+    } catch (RuntimeException expected) {
+      assertSame(a2, expected);
+      assertEquals(1, expected.getSuppressed().length);
+      Throwable firstSuppressed = expected.getSuppressed()[0];
+      assertSame(b, firstSuppressed);
+    }
+    assertEquals(1, calledCount[0]);
+
+    // Throw the same exception instance twice, ensure it only arrives once
+    s = Stream.of(1, 2, 3);
+
+    RuntimeException t = new RuntimeException("a");
+    s
+        .onClose(() -> {
+          throw t;
+        })
+        .onClose(() -> {
+          throw t;
+        });
+
+    try {
+      s.close();
+      fail("RuntimeException expected");
+    } catch (RuntimeException expected) {
+      assertSame(t, expected);
+      assertEquals(0, expected.getSuppressed().length);
+    }
+  }
+}
\ No newline at end of file
