diff --git a/user/super/com/google/gwt/emul/java/util/stream/Collector.java b/user/super/com/google/gwt/emul/java/util/stream/Collector.java
new file mode 100644
index 0000000..ea96bb5
--- /dev/null
+++ b/user/super/com/google/gwt/emul/java/util/stream/Collector.java
@@ -0,0 +1,142 @@
+/*
+ * 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.checkNotNull;
+
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+/**
+ * See <a
+ * href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collector.html">the
+ * official Java API doc</a> for details.
+ * @param <T> the type of data to be collected
+ * @param <A> the type of accumulator used to track results
+ * @param <R> the final output data type
+ */
+public interface Collector<T,A,R> {
+
+  /**
+   * See <a
+   * href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collector.Characteristics.html">the
+   * official Java API doc</a> for details.
+   */
+  enum Characteristics { CONCURRENT, IDENTITY_FINISH, UNORDERED }
+
+  static <T,A,R> Collector<T,A,R> of(Supplier<A> supplier, BiConsumer<A,T> accumulator, BinaryOperator<A> combiner, Function<A,R> finisher, Collector.Characteristics... characteristics) {
+    checkNotNull(supplier);
+    checkNotNull(accumulator);
+    checkNotNull(combiner);
+    checkNotNull(finisher);
+    checkNotNull(characteristics);
+    return new CollectorImpl<>(
+        supplier,
+        accumulator,
+        combiner,
+        finisher,
+        characteristics
+    );
+  }
+
+  static <T,R> Collector<T,R,R> of(Supplier<R> supplier, BiConsumer<R,T> accumulator, BinaryOperator<R> combiner, Collector.Characteristics... characteristics) {
+    checkNotNull(supplier);
+    checkNotNull(accumulator);
+    checkNotNull(combiner);
+    checkNotNull(characteristics);
+    return new CollectorImpl<>(
+        supplier,
+        accumulator,
+        combiner,
+        Function.identity(),
+        Collections.unmodifiableSet(EnumSet.of(Characteristics.IDENTITY_FINISH, characteristics))
+    );
+  }
+
+  Supplier<A> supplier();
+
+  BiConsumer<A,T> accumulator();
+
+  Set<Collector.Characteristics> characteristics();
+
+  BinaryOperator<A> combiner();
+
+  Function<A,R> finisher();
+
+  /**
+   * Simple internal implementation of a collector, holding each of the functions in a field.
+   */
+  static final class CollectorImpl<T, A, R> implements Collector<T, A, R> {
+    private final Supplier<A> supplier;
+    private final BiConsumer<A, T> accumulator;
+    private final Set<Collector.Characteristics> characteristics;
+    private final BinaryOperator<A> combiner;
+    private final Function<A, R> finisher;
+
+    public CollectorImpl(Supplier<A> supplier, BiConsumer<A, T> accumulator, BinaryOperator<A> combiner, Function<A, R> finisher, Characteristics... characteristics) {
+      this.supplier = supplier;
+      this.accumulator = accumulator;
+      if (characteristics.length == 0) {
+        this.characteristics = Collections.emptySet();
+      } else if (characteristics.length == 1) {
+        this.characteristics = Collections.singleton(characteristics[0]);
+      } else {
+        this.characteristics = Collections.unmodifiableSet(EnumSet.of(characteristics[0], characteristics));
+      }
+      this.combiner = combiner;
+      this.finisher = finisher;
+    }
+
+    public CollectorImpl(Supplier<A> supplier, BiConsumer<A, T> accumulator, BinaryOperator<A> combiner, Function<A, R> finisher, Set<Characteristics> characteristics) {
+      this.supplier = supplier;
+      this.accumulator = accumulator;
+      this.combiner = combiner;
+      this.finisher = finisher;
+      this.characteristics = characteristics;
+    }
+
+    @Override
+    public Supplier<A> supplier() {
+      return supplier;
+    }
+
+    @Override
+    public BiConsumer<A, T> accumulator() {
+      return accumulator;
+    }
+
+    @Override
+    public BinaryOperator<A> combiner() {
+      return combiner;
+    }
+
+    @Override
+    public Function<A, R> finisher() {
+      return finisher;
+    }
+
+    @Override
+    public Set<Characteristics> characteristics() {
+      return characteristics;
+    }
+  }
+}
\ No newline at end of file
diff --git a/user/super/com/google/gwt/emul/java/util/stream/Collectors.java b/user/super/com/google/gwt/emul/java/util/stream/Collectors.java
new file mode 100644
index 0000000..620e0ed
--- /dev/null
+++ b/user/super/com/google/gwt/emul/java/util/stream/Collectors.java
@@ -0,0 +1,339 @@
+/*
+ * 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.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.DoubleSummaryStatistics;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.IntSummaryStatistics;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.LongSummaryStatistics;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.StringJoiner;
+import java.util.function.BiConsumer;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+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;
+
+/**
+ * See <a
+ * href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html">the
+ * official Java API doc</a> for details.
+ */
+public final class Collectors {
+  public static <T> Collector<T,?,Double> averagingDouble(ToDoubleFunction<? super T> mapper) {
+    // TODO simplify to only collect average if possible
+    return collectingAndThen(summarizingDouble(mapper), DoubleSummaryStatistics::getAverage);
+  }
+
+  public static <T> Collector<T,?,Double> averagingInt(ToIntFunction<? super T> mapper) {
+    // TODO simplify to only collect average if possible
+    return collectingAndThen(summarizingInt(mapper), IntSummaryStatistics::getAverage);
+  }
+
+  public static <T> Collector<T,?,Double> averagingLong(ToLongFunction<? super T> mapper) {
+    // TODO simplify to only collect average if possible
+    return collectingAndThen(summarizingLong(mapper), LongSummaryStatistics::getAverage);
+  }
+
+  public static <T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream, Function<R,RR> finisher) {
+    return new Collector.CollectorImpl<>(
+        downstream.supplier(),
+        downstream.accumulator(),
+        downstream.combiner(),
+        downstream.finisher().andThen(finisher),
+        removeIdentFinisher(downstream.characteristics())
+    );
+  }
+
+  public static <T> Collector<T,?,Long> counting() {
+    return reducing(0L, item -> 1L, Long::sum);
+  }
+
+  public static <T,K> Collector<T,?,Map<K,List<T>>> groupingBy(Function<? super T,? extends K> classifier) {
+    // TODO inline this and avoid the finisher extra work of copying from a map to another map
+    //      kept separate for now to unify implementations and reduce testing required
+    return groupingBy(classifier, toList());
+  }
+
+  public static <T,K,A,D> Collector<T,?,Map<K,D>> groupingBy(Function<? super T,? extends K> classifier, Collector<? super T,A,D> downstream) {
+    return groupingBy(classifier, HashMap::new, downstream);
+  }
+
+  public static <T,K,D,A,M extends Map<K,D>> Collector<T,?,M> groupingBy(Function<? super T,? extends K> classifier, Supplier<M> mapFactory, Collector<? super T,A,D> downstream) {
+    return Collector.<T, Map<K, List<T>>, M>of(
+        LinkedHashMap::new,
+        (m, o) -> {
+          K k = classifier.apply(o);
+          List<T> l = m.get(k);
+          if (l == null) {
+            l = new ArrayList<>();
+            m.put(k, l);
+          }
+          l.add(o);
+
+        },
+        (m1, m2) -> mergeAll(m1, m2, Collectors::addAll),
+        m -> {
+          M result = mapFactory.get();
+          for (Map.Entry<K, List<T>> entry : m.entrySet()) {
+            result.put(entry.getKey(), streamAndCollect(downstream, entry.getValue()));
+          }
+          return result;
+        });
+  }
+
+//  not supported
+//  public static <T,K> Collector<T,?,ConcurrentMap<K,List<T>>> groupingByConcurrent(Function<? super T,? extends K> classifier)
+//  public static <T,K,A,D> Collector<T,?,ConcurrentMap<K,D>> groupingByConcurrent(Function<? super T,? extends K> classifier, Collector<? super T,A,D> downstream)
+//  public static <T,K,A,D,M extends ConcurrentMap<K,D>> Collector<T,?,M> groupingByConcurrent(Function<? super T,? extends K> classifier, Supplier<M> mapFactory, Collector<? super T,A,D> downstream)
+
+  public static Collector<CharSequence,?,String> joining() {
+    // specific implementation rather than calling joining("") since we don't need to worry about
+    // appending delimiters between empty strings
+    return Collector.of(
+        StringBuilder::new,
+        StringBuilder::append,
+        StringBuilder::append,
+        StringBuilder::toString
+    );
+  }
+
+  public static Collector<CharSequence,?,String> joining(CharSequence delimiter) {
+    return joining(delimiter, "", "");
+  }
+
+  public static Collector<CharSequence,?,String> joining(final CharSequence delimiter, CharSequence prefix, CharSequence suffix) {
+    return Collector.of(
+        () -> new StringJoiner(delimiter, prefix, suffix),
+        StringJoiner::add,
+        StringJoiner::merge,
+        StringJoiner::toString
+    );
+  }
+
+  public static <T,U,A,R> Collector<T,?,R> mapping(final Function<? super T,? extends U> mapper, final Collector<? super U,A,R> downstream) {
+    return new Collector.CollectorImpl<>(
+        downstream.supplier(),
+        (BiConsumer<A, T>) (A a, T t) -> {
+          downstream.accumulator().accept(a, mapper.apply(t));
+        },
+        downstream.combiner(),
+        downstream.finisher(),
+        downstream.characteristics()
+    );
+  }
+
+  public static <T> Collector<T,?,Optional<T>> maxBy(Comparator<? super T> comparator) {
+    return minBy(comparator.reversed());
+  }
+
+  public static <T> Collector<T,?,Optional<T>> minBy(final Comparator<? super T> comparator) {
+    return reducing((a, b) -> comparator.compare(a, b) < 0 ? a : b);
+  }
+
+  public static <T> Collector<T,?,Map<Boolean,List<T>>> partitioningBy(Predicate<? super T> predicate) {
+    // calling groupBy directly rather than partioningBy so that it can be optimized later
+    return groupingBy(predicate::test);
+  }
+
+  public static <T,D,A> Collector<T,?,Map<Boolean,D>> partitioningBy(Predicate<? super T> predicate, Collector<? super T,A,D> downstream) {
+    return groupingBy(predicate::test, downstream);
+  }
+
+  public static <T> Collector<T,?,Optional<T>> reducing(BinaryOperator<T> op) {
+    return reducing(Optional.empty(), Optional::of, (a, b) -> {
+      if (!a.isPresent()) {
+        return b;
+      }
+      if (!b.isPresent()) {
+        return a;
+      }
+      return Optional.of(op.apply(a.get(), b.get()));
+    });
+  }
+
+  public static <T> Collector<T,?,T> reducing(T identity, BinaryOperator<T> op) {
+    return reducing(identity, Function.identity(), op);
+  }
+
+  @SuppressWarnings("unchecked")
+  public static <T,U> Collector<T,?,U> reducing(final U identity, final Function<? super T,? extends U> mapper, BinaryOperator<U> op) {
+    return Collector.of(
+      () -> new Object[]{identity},
+      (u, t) -> u[0] = op.apply((U) u[0], mapper.apply(t)),
+      (Object[] u1, Object[] u2) -> {
+        u1[0] = op.apply((U) u1[0], (U) u2[0]);
+        return u1;
+      },
+      (Object[] a) -> (U) a[0]
+    );
+  }
+
+  public static <T> Collector<T,?,DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper) {
+    return Collector.of(
+        DoubleSummaryStatistics::new,
+        (stats, item) -> stats.accept(mapper.applyAsDouble(item)),
+        (t, u) -> {
+          t.combine(u);
+          return t;
+        },
+        Collector.Characteristics.UNORDERED, Collector.Characteristics.IDENTITY_FINISH
+    );
+  }
+
+  public static <T> Collector<T,?,IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper) {
+    return Collector.of(
+        IntSummaryStatistics::new,
+        (stats, item) -> stats.accept(mapper.applyAsInt(item)),
+        (t, u) -> {
+          t.combine(u);
+          return t;
+        },
+        Collector.Characteristics.UNORDERED, Collector.Characteristics.IDENTITY_FINISH
+    );
+  }
+
+  public static <T> Collector<T,?,LongSummaryStatistics> summarizingLong(ToLongFunction<? super T> mapper) {
+    return Collector.of(
+        LongSummaryStatistics::new,
+        (stats, item) -> stats.accept(mapper.applyAsLong(item)),
+        (t, u) -> {
+          t.combine(u);
+          return t;
+        },
+        Collector.Characteristics.UNORDERED, Collector.Characteristics.IDENTITY_FINISH
+    );
+  }
+
+  public static <T> Collector<T,?,Double> summingDouble(final ToDoubleFunction<? super T> mapper) {
+    // TODO simplify to only collect sum if possible
+    return collectingAndThen(summarizingDouble(mapper), DoubleSummaryStatistics::getSum);
+  }
+
+  public static <T> Collector<T,?,Integer> summingInt(ToIntFunction<? super T> mapper) {
+    // TODO simplify to only collect sum if possible
+    return collectingAndThen(summarizingInt(mapper), intSummaryStatistics -> (int) intSummaryStatistics.getSum());
+  }
+
+  public static <T> Collector<T,?,Long> summingLong(ToLongFunction<? super T> mapper) {
+    // TODO simplify to only collect sum if possible
+    return collectingAndThen(summarizingLong(mapper), LongSummaryStatistics::getSum);
+  }
+
+  public static <T,C extends Collection<T>> Collector<T,?,C> toCollection(final Supplier<C> collectionFactory) {
+    return Collector.of(
+        collectionFactory,
+        Collection::add,
+        // TODO switch to a lambda reference once #9333 is fixed
+        (c1, c2) -> addAll(c1, c2),
+        Collector.Characteristics.IDENTITY_FINISH
+    );
+  }
+
+//  not supported
+//  public static <T,K,U> Collector<T,?,ConcurrentMap<K,U>> toConcurrentMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper)
+//  public static <T,K,U> Collector<T,?,ConcurrentMap<K,U>> toConcurrentMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction)
+//  public static <T,K,U,M extends ConcurrentMap<K,U>> Collector<T,?,M> toConcurrentMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier)
+
+  public static <T> Collector<T,?,List<T>> toList() {
+    return toCollection(ArrayList::new);
+  }
+
+  public static <T,K,U> Collector<T,?,Map<K,U>> toMap(final Function<? super T,? extends K> keyMapper, final Function<? super T,? extends U> valueMapper) {
+    return toMap(keyMapper, valueMapper, (m1, m2) -> { throw new IllegalStateException("Can't assign multiple values to the same key"); });
+  }
+
+  public static <T,K,U> Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction) {
+    return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
+  }
+
+  public static <T,K,U,M extends Map<K,U>> Collector<T,?,M> toMap(final Function<? super T,? extends K> keyMapper, final Function<? super T,? extends U> valueMapper, final BinaryOperator<U> mergeFunction, final Supplier<M> mapSupplier) {
+    return Collector.of(
+        mapSupplier,
+        (map, item) -> {
+          K key = keyMapper.apply(item);
+          U newValue = valueMapper.apply(item);
+          if (map.containsKey(key)) {
+            map.put(key, mergeFunction.apply(map.get(key), newValue));
+          } else {
+            map.put(key, newValue);
+          }
+        },
+        (m1, m2) -> mergeAll(m1, m2, mergeFunction),
+        Collector.Characteristics.IDENTITY_FINISH
+    );
+  }
+
+  public static <T> Collector<T,?,Set<T>> toSet() {
+    return Collector.<T, HashSet<T>, Set<T>>of(
+        HashSet::new,
+        HashSet::add,
+        // TODO switch to a lambda reference once #9333 is fixed
+        (c1, c2) -> addAll(c1, c2),
+        // this is Function.identity, but Java doesn't like it here to change types.
+        s -> s,
+        Collector.Characteristics.UNORDERED, Collector.Characteristics.IDENTITY_FINISH
+    );
+  }
+
+  private static Set<Collector.Characteristics> removeIdentFinisher(Set<Collector.Characteristics> characteristics) {
+    if (!characteristics.contains(Collector.Characteristics.IDENTITY_FINISH)) {
+      return characteristics;
+    }
+
+    if (characteristics.size() == 1) {
+      return Collections.emptySet();
+    }
+
+    EnumSet<Collector.Characteristics> result = EnumSet.copyOf(characteristics);
+    result.remove(Collector.Characteristics.IDENTITY_FINISH);
+    return Collections.unmodifiableSet(result);
+  }
+
+  private static <T, D, A> D streamAndCollect(Collector<? super T, A, D> downstream, List<T> list) {
+    A a = downstream.supplier().get();
+    for (T t : list) {
+      downstream.accumulator().accept(a, t);
+    }
+    return downstream.finisher().apply(a);
+  }
+
+  private static <K, V, M extends Map<K, V>> M mergeAll(M m1, M m2, BinaryOperator<V> mergeFunction) {
+    for (Map.Entry<K, V> entry : m2.entrySet()) {
+      m1.merge(entry.getKey(), entry.getValue(), mergeFunction);
+    }
+    return m1;
+  }
+
+  private static <T, C extends Collection<T>> C addAll(C collection, Collection<T> items) {
+    collection.addAll(items);
+    return collection;
+  }
+}
diff --git a/user/test/com/google/gwt/emultest/EmulJava8Suite.java b/user/test/com/google/gwt/emultest/EmulJava8Suite.java
index 62c6526..fbe0c91 100644
--- a/user/test/com/google/gwt/emultest/EmulJava8Suite.java
+++ b/user/test/com/google/gwt/emultest/EmulJava8Suite.java
@@ -38,6 +38,7 @@
 import com.google.gwt.emultest.java8.util.StringJoinerTest;
 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.junit.tools.GWTTestSuite;
 
 import junit.framework.Test;
@@ -76,6 +77,10 @@
     suite.addTestSuite(DoubleSummaryStatisticsTest.class);
     suite.addTestSuite(IntSummaryStatisticsTest.class);
     suite.addTestSuite(LongSummaryStatisticsTest.class);
+
+    //-- java.util.stream
+    suite.addTestSuite(CollectorsTest.class);
+
     return suite;
   }
 }
diff --git a/user/test/com/google/gwt/emultest/java8/util/stream/CollectorsTest.java b/user/test/com/google/gwt/emultest/java8/util/stream/CollectorsTest.java
new file mode 100644
index 0000000..7a14614
--- /dev/null
+++ b/user/test/com/google/gwt/emultest/java8/util/stream/CollectorsTest.java
@@ -0,0 +1,546 @@
+/*
+ * 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.Collectors.averagingDouble;
+import static java.util.stream.Collectors.averagingInt;
+import static java.util.stream.Collectors.averagingLong;
+import static java.util.stream.Collectors.collectingAndThen;
+import static java.util.stream.Collectors.counting;
+import static java.util.stream.Collectors.groupingBy;
+import static java.util.stream.Collectors.joining;
+import static java.util.stream.Collectors.mapping;
+import static java.util.stream.Collectors.maxBy;
+import static java.util.stream.Collectors.minBy;
+import static java.util.stream.Collectors.partitioningBy;
+import static java.util.stream.Collectors.summarizingDouble;
+import static java.util.stream.Collectors.summarizingInt;
+import static java.util.stream.Collectors.summarizingLong;
+import static java.util.stream.Collectors.summingDouble;
+import static java.util.stream.Collectors.summingInt;
+import static java.util.stream.Collectors.summingLong;
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toMap;
+import static java.util.stream.Collectors.toSet;
+
+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.DoubleSummaryStatistics;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.IntSummaryStatistics;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.LongSummaryStatistics;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.BiPredicate;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collector;
+
+/**
+ * Tests {@link java.util.stream.Collectors}.
+ * <p />
+ * Methods that are presently only tested indirectly:
+ * <ul>
+ *   <li>reducing: counting, minBy/maxBy use this</li>
+ *   <li>toCollection tested by toList (toSet now uses its own impl)</li>
+ * </ul>
+ */
+public class CollectorsTest extends EmulTestBase {
+
+  public void testAveragingDouble() {
+    Collector<Double, ?, Double> c = averagingDouble(Double::doubleValue);
+    applyItems((4.0 + 8.0) / 2.0, c, 4.0, 8.0);
+
+    assertZeroItemsCollectedAs(0D, c);
+    assertSingleItemCollectedAs(5D, c, 5D);
+  }
+
+  public void testAveragingInt() {
+    Collector<Integer, ?, Double> c = averagingInt(Integer::intValue);
+    applyItems((4.0 + 8.0) / 2.0, c, 4, 8);
+
+    assertZeroItemsCollectedAs(0D, c);
+    assertSingleItemCollectedAs(5D, c, 5);
+  }
+
+  public void testAveragingLong() {
+    Collector<Long, ?, Double> c = averagingLong(Long::longValue);
+    applyItems((4.0 + 8.0) / 2.0, c, 4L, 8L);
+
+    assertZeroItemsCollectedAs(0D, c);
+    assertSingleItemCollectedAs(5D, c, 5L);
+  }
+
+  public void testCollectingAndThen() {
+    Collector<Object, ?, List<Object>> listIdentityCollector = collectingAndThen(toList(), Function.identity());
+    // same test as toList():
+    // same items (allow dups)
+    applyItems(
+        Arrays.asList("a", "a"),
+        listIdentityCollector,
+        "a", "a"
+    );
+
+    // ordered
+    applyItems(
+        Arrays.asList("a", "b"),
+        listIdentityCollector,
+        "a", "b"
+    );
+    assertZeroItemsCollectedAs(Collections.emptyList(), listIdentityCollector);
+    assertSingleItemCollectedAs(Collections.singletonList("a"), listIdentityCollector, "a");
+
+    Collector<Object, ?, Integer> uglyCount = collectingAndThen(toList(), List::size);
+    // (nearly) same test as counting():
+    applyItems(2, uglyCount, "1", new Object());
+
+    assertZeroItemsCollectedAs(0, uglyCount);
+    assertSingleItemCollectedAs(1, uglyCount, new Object());
+  }
+
+  public void testCounting() {
+    Collector<Object, ?, Long> c = counting();
+    applyItems(2L, c, "1", new Object());
+
+    assertZeroItemsCollectedAs(0L, c);
+    assertSingleItemCollectedAs(1L, c, new Object());
+  }
+
+  public void testGroupingBy() {
+    Collector<String, ?, Map<String, List<String>>> c1 = groupingBy(Function.identity());
+
+    Map<String, List<String>> mapOfLists = new HashMap<>();
+    mapOfLists.put("a", Arrays.asList("a", "a"));
+    applyItems(mapOfLists, c1, "a", "a");
+    mapOfLists.clear();
+    mapOfLists.put("a", Collections.singletonList("a"));
+    mapOfLists.put("b", Collections.singletonList("b"));
+    applyItems(mapOfLists, c1, "a", "b");
+
+    assertZeroItemsCollectedAs(Collections.emptyMap(), c1);
+    assertSingleItemCollectedAs(Collections.singletonMap("a", Collections.singletonList("a")), c1, "a");
+
+    Collector<String, ?, LinkedHashMap<String, Set<String>>> c2 = groupingBy(Function.identity(), LinkedHashMap::new, toSet());
+
+    LinkedHashMap<String, Set<String>> linkedMapOfSets = new LinkedHashMap<>();
+    linkedMapOfSets.put("a", Collections.singleton("a"));
+    applyItems(linkedMapOfSets, c2, "a", "a");
+    linkedMapOfSets.clear();
+    linkedMapOfSets.put("a", Collections.singleton("a"));
+    linkedMapOfSets.put("b", Collections.singleton("b"));
+    applyItems(linkedMapOfSets, c2, "a", "b");
+
+    // check to make sure we actually get the linked results, and that they are ordered how we want them
+    LinkedHashMap<String, Set<String>> out = applyItemsWithoutSplitting(c2, "a", "b");
+    assertEquals(Arrays.asList("a", "b"), new ArrayList<>(out.keySet()));
+    out = applyItemsWithoutSplitting(c2, "b", "a");
+    assertEquals(Arrays.asList("b", "a"), new ArrayList<>(out.keySet()));
+
+    assertZeroItemsCollectedAs(new LinkedHashMap<>(), c2);
+    linkedMapOfSets.clear();
+    linkedMapOfSets.put("a", Collections.singleton("a"));
+    assertSingleItemCollectedAs(linkedMapOfSets, c2, "a");
+  }
+
+  public void testJoining() {
+    Collector<CharSequence, ?, String> c = joining();
+    applyItems("ab", c, "a", "b");
+    applyItems("a,", c, "a", ",");
+    applyItems("", c, "", "");
+    assertZeroItemsCollectedAs("", c);
+    assertSingleItemCollectedAs("a", c, "a");
+    assertSingleItemCollectedAs("", c, "");
+
+    c = joining(",");
+    applyItems("a,b", c, "a", "b");
+    applyItems("a,,", c, "a", ",");
+    applyItems(",", c, "", "");
+    assertZeroItemsCollectedAs("", c);
+    assertSingleItemCollectedAs("a", c, "a");
+    assertSingleItemCollectedAs("", c, "");
+
+    c = joining("-", "{", "}");
+    applyItems("{a-b}", c, "a", "b");
+    assertZeroItemsCollectedAs("{}", c);
+    assertSingleItemCollectedAs("{a}", c, "a");
+    assertSingleItemCollectedAs("{}", c, "");
+  }
+
+  public void testMapping() {
+    Collector<String, ?, List<String>> identityMapping = mapping(Function.identity(), toList());
+    // same test as toList():
+    // same items (allow dups)
+    applyItems(
+        Arrays.asList("a", "a"),
+        identityMapping,
+        "a", "a"
+    );
+
+    // ordered
+    applyItems(
+        Arrays.asList("a", "b"),
+        identityMapping,
+        "a", "b"
+    );
+    assertZeroItemsCollectedAs(Collections.emptyList(), identityMapping);
+    assertSingleItemCollectedAs(Collections.singletonList("a"), identityMapping, "a");
+
+    Collector<Integer, ?, List<String>> numberMapping = mapping(s -> "#" + s, toList());
+    // poke the same tests as list, make sure the mapper is run
+    applyItems(
+        Arrays.asList("#1", "#2"),
+        numberMapping,
+        1, 2
+    );
+
+    // ordered
+    applyItems(
+        Arrays.asList("#1", "#2"),
+        numberMapping,
+        1, 2
+    );
+    assertZeroItemsCollectedAs(Collections.emptyList(), numberMapping);
+    assertSingleItemCollectedAs(Collections.singletonList("#10"), numberMapping, 10);
+  }
+
+  public void testMaxBy() {
+    Collector<String, ?, Optional<String>> c = maxBy(Comparator.naturalOrder());
+    applyItems(Optional.of("z"), c, "a", "z");
+    applyItems(Optional.of("z"), c, "z", "a");
+
+    assertZeroItemsCollectedAs(Optional.empty(), c);
+    assertSingleItemCollectedAs(Optional.of("foo"), c, "foo");
+  }
+
+  public void testMinBy() {
+    Collector<String, ?, Optional<String>> c = minBy(Comparator.naturalOrder());
+    applyItems(Optional.of("a"), c, "a", "z");
+    applyItems(Optional.of("a"), c, "z", "a");
+
+    assertZeroItemsCollectedAs(Optional.empty(), c);
+    assertSingleItemCollectedAs(Optional.of("foo"), c, "foo");
+  }
+
+  public void testPartitioningBy() {
+    Collector<Boolean, ?, Map<Boolean, List<Boolean>>> c1 = partitioningBy(Boolean::valueOf);
+
+    Map<Boolean, List<Boolean>> mapOfLists = new HashMap<>();
+    mapOfLists.put(true, Collections.singletonList(true));
+    mapOfLists.put(false, Collections.singletonList(false));
+    applyItems(mapOfLists, c1, true, false);
+    mapOfLists.clear();
+    mapOfLists.put(true, Arrays.asList(true, true));
+    applyItems(mapOfLists, c1, true, true);
+    mapOfLists.clear();
+    mapOfLists.put(false, Arrays.asList(false, false));
+    applyItems(mapOfLists, c1, false, false);
+
+    assertZeroItemsCollectedAs(Collections.emptyMap(), c1);
+    assertSingleItemCollectedAs(Collections.singletonMap(true, Collections.singletonList(true)), c1, true);
+    assertSingleItemCollectedAs(Collections.singletonMap(false, Collections.singletonList(false)), c1, false);
+
+    Collector<Boolean, ?, Map<Boolean, Set<Boolean>>> c2 = partitioningBy(Boolean::valueOf, toSet());
+
+    Map<Boolean, Set<Boolean>> mapOfSets = new HashMap<>();
+    mapOfSets.put(true, Collections.singleton(true));
+    mapOfSets.put(false, Collections.singleton(false));
+    applyItems(mapOfSets, c2, true, false);
+    mapOfSets.clear();
+    mapOfSets.put(true, Collections.singleton(true));
+    applyItems(mapOfSets, c2, true, true);
+    mapOfSets.clear();
+    mapOfSets.put(false, Collections.singleton(false));
+    applyItems(mapOfSets, c2, false, false);
+  }
+
+  public void testSummarizingDouble() {
+    Collector<Double, ?, DoubleSummaryStatistics> c = summarizingDouble(Double::doubleValue);
+    DoubleSummaryStatistics stats = new DoubleSummaryStatistics();
+    stats.accept(5.1);
+    stats.accept(7);
+    BiPredicate<DoubleSummaryStatistics, DoubleSummaryStatistics> equals = (s1, s2) ->
+        s1.getSum() == s2.getSum()
+            && s1.getAverage() == s2.getAverage()
+            && s1.getCount() == s2.getCount()
+            && s1.getMin() == s2.getMin()
+            && s1.getMax() == s2.getMax();
+    applyItems(stats, c, 5.1, 7.0, equals);
+    applyItems(stats, c, 7.0, 5.1, equals);//probably unnecessary to run these backward
+
+    assertZeroItemsCollectedAs(new DoubleSummaryStatistics(), c, equals);
+    stats = new DoubleSummaryStatistics();
+    stats.accept(7.3);
+    assertSingleItemCollectedAs(stats, c, 7.3, equals);
+  }
+
+  public void testSummarizingInt() {
+    Collector<Integer, ?, IntSummaryStatistics> c = summarizingInt(Integer::intValue);
+    IntSummaryStatistics stats = new IntSummaryStatistics();
+    stats.accept(2);
+    stats.accept(10);
+    BiPredicate<IntSummaryStatistics, IntSummaryStatistics> equals = (s1, s2) ->
+        s1.getSum() == s2.getSum()
+            && s1.getAverage() == s2.getAverage()
+            && s1.getCount() == s2.getCount()
+            && s1.getMin() == s2.getMin()
+            && s1.getMax() == s2.getMax();
+    applyItems(stats, c, 2, 10, equals);
+    applyItems(stats, c, 10, 2, equals);
+
+    assertZeroItemsCollectedAs(new IntSummaryStatistics(), c, equals);
+    stats = new IntSummaryStatistics();
+    stats.accept(7);
+    assertSingleItemCollectedAs(stats, c, 7, equals);
+  }
+
+  public void testSummarizingLong() {
+    Collector<Long, ?, LongSummaryStatistics> c = summarizingLong(Long::longValue);
+    LongSummaryStatistics stats = new LongSummaryStatistics();
+    stats.accept(2);
+    stats.accept(10);
+    BiPredicate<LongSummaryStatistics, LongSummaryStatistics> equals = (s1, s2) ->
+        s1.getSum() == s2.getSum()
+            && s1.getAverage() == s2.getAverage()
+            && s1.getCount() == s2.getCount()
+            && s1.getMin() == s2.getMin()
+            && s1.getMax() == s2.getMax();
+    applyItems(stats, c, 2L, 10L, equals);
+    applyItems(stats, c, 10L, 2L, equals);
+
+    assertZeroItemsCollectedAs(new LongSummaryStatistics(), c, equals);
+    stats = new LongSummaryStatistics();
+    stats.accept(7L);
+    assertSingleItemCollectedAs(stats, c, 7L, equals);
+  }
+
+  public void testSummingDouble() {
+    Collector<Double, ?, Double> c = summingDouble(Double::doubleValue);
+    applyItems(4.1 + 8.2, c, 4.1, 8.2);
+
+    assertZeroItemsCollectedAs(0d, c);
+    assertSingleItemCollectedAs(7.3, c, 7.3);
+  }
+
+  public void testSummingInt() {
+    Collector<Integer, ?, Integer> c = summingInt(Integer::intValue);
+    applyItems(4 + 8, c, 4, 8);
+
+    assertZeroItemsCollectedAs(0, c);
+    assertSingleItemCollectedAs(7, c, 7);
+  }
+
+  public void testSummingLong() {
+    Collector<Long, ?, Long> c = summingLong(Long::longValue);
+    applyItems(4L + 8L, c, 4L, 8L);
+
+    assertZeroItemsCollectedAs(0L, c);
+    assertSingleItemCollectedAs(5L, c, 5L);
+  }
+
+  public void testList() {
+    Collector<String, ?, List<String>> c = toList();
+
+    // same items (allow dups)
+    applyItems(
+        Arrays.asList("a", "a"),
+        c,
+        "a", "a"
+    );
+
+    // ordered
+    applyItems(
+        Arrays.asList("a", "b"),
+        c,
+        "a", "b"
+    );
+    assertZeroItemsCollectedAs(Collections.emptyList(), c);
+    assertSingleItemCollectedAs(Collections.singletonList("a"), c, "a");
+  }
+
+  public void testMap() {
+    Collector<String, ?, Map<String, String>> c = toMap(Function.identity(), Function.identity());
+
+    // two distinct items
+    Map<String, String> map = new HashMap<>();
+    map.put("a", "a");
+    map.put("b", "b");
+    applyItems(map, c, "a", "b");
+
+    // inline applyItems and test each to confirm failure for duplicates
+    try {
+      applyItemsWithoutSplitting(c, "a", "a");
+      fail("expected IllegalStateException");
+    } catch (IllegalStateException expected) {
+    }
+    try {
+      applyItemsWithSplitting(c, "a", "a");
+      fail("expected IllegalStateException");
+    } catch (IllegalStateException expected) {
+    }
+
+    assertZeroItemsCollectedAs(Collections.emptyMap(), c);
+    assertSingleItemCollectedAs(Collections.singletonMap("a", "a"), c, "a");
+
+    List<String> seen = new ArrayList<>();
+    c = toMap(Function.identity(), Function.identity(), (s, s2) -> {
+      seen.add("first: " + s);
+      seen.add("second: " + s2);
+      return s + "," + s2;
+    });
+    map = new HashMap<>();
+    map.put("a", "a,a");
+    applyItems(map, c, "a", "a");
+    assertEquals(Arrays.asList("first: a", "second: a", "first: a", "second: a"), seen);
+  }
+
+  public void testSet() {
+    Collector<String, ?, Set<String>> c = toSet();
+
+    // same items (no dups)
+    applyItems(
+        Collections.singleton("a"),
+        c,
+        "a", "a"
+    );
+
+    // different items
+    applyItems(
+        new HashSet<>(Arrays.asList("a", "b")),
+        c,
+        "a", "b"
+    );
+
+    assertZeroItemsCollectedAs(Collections.emptySet(), c);
+    assertSingleItemCollectedAs(Collections.singleton("a"), c, "a");
+  }
+
+  /**
+   * This method attempts to apply a collector to items as a stream might do, so that we
+   * can simply verify the output. Taken from the Collector class's javadoc.
+   */
+  private static <T, A, R> void applyItems(R expected, Collector<T, A, R> collector, T t1, T t2, BiPredicate<R, R> equals) {
+    assertTrue("failed without splitting", equals.test(expected, applyItemsWithoutSplitting(collector, t1, t2)));
+    assertTrue("failed with splitting", equals.test(expected, applyItemsWithSplitting(collector, t1, t2)));
+  }
+
+  /**
+   * This method attempts to apply a collector to items as a stream might do, so that we
+   * can simply verify the output. Taken from the Collector class's javadoc.
+   */
+  private static <T, A, R> void applyItems(R expected, Collector<T, A, R> collector, T t1, T t2) {
+    applyItems(expected, collector, t1, t2, Object::equals);
+  }
+
+  /**
+   * Helper for applyItems.
+   */
+  private static <T, A, R> R applyItemsWithoutSplitting(Collector<T, A, R> collector, T t1, T t2) {
+    Supplier<A> supplier = collector.supplier();
+    BiConsumer<A, T> accumulator = collector.accumulator();
+    // unused in this impl
+    BinaryOperator<A> combiner = collector.combiner();
+    Function<A, R> finisher = collector.finisher();
+
+    A a1 = supplier.get();
+
+    accumulator.accept(a1, t1);
+    accumulator.accept(a1, t2);
+
+    // result without splitting
+    R r1 = finisher.apply(a1);
+    return r1;
+  }
+
+  /**
+   * Helper for applyItems.
+   */
+  private static <T, A, R> R applyItemsWithSplitting(Collector<T, A, R> collector, T t1, T t2) {
+    Supplier<A> supplier = collector.supplier();
+    BiConsumer<A, T> accumulator = collector.accumulator();
+    // actually used in this impl
+    BinaryOperator<A> combiner = collector.combiner();
+    Function<A, R> finisher = collector.finisher();
+
+    A a2 = supplier.get();
+    accumulator.accept(a2, t1);
+    A a3 = supplier.get();
+    accumulator.accept(a3, t2);
+
+    // result with splitting
+    R r2 = finisher.apply(combiner.apply(a2, a3));
+    return r2;
+  }
+
+  private static <T, A, R> void assertZeroItemsCollectedAs(R expected, Collector<T, A, R> collector) {
+    assertZeroItemsCollectedAs(expected, collector, Object::equals);
+  }
+
+  private static <T, A, R> void assertZeroItemsCollectedAs(R expected, Collector<T, A, R> collector, BiPredicate<R, R> equals) {
+    Supplier<A> supplier = collector.supplier();
+    // unused in this impl
+    BiConsumer<A, T> accumulator = collector.accumulator();
+    // shouldn't really be used, just handy to poke the internals quick
+    BinaryOperator<A> combiner = collector.combiner();
+    Function<A, R> finisher = collector.finisher();
+
+    R actual = finisher.apply(supplier.get());
+    assertTrue(equals, expected, actual);
+    // doesn't actually ever happen, just internal checks
+    actual = finisher.apply(combiner.apply(supplier.get(), supplier.get()));
+    assertTrue(equals, expected, actual);
+  }
+
+  private static <T, A, R> void assertSingleItemCollectedAs(R expected, Collector<T, A, R> collector, T item) {
+    assertSingleItemCollectedAs(expected, collector, item, Object::equals);
+  }
+
+  private static <T, A, R> void assertSingleItemCollectedAs(R expected, Collector<T, A, R> collector, T item, BiPredicate<R, R> equals) {
+    Supplier<A> supplier = collector.supplier();
+    BiConsumer<A, T> accumulator = collector.accumulator();
+    // shouldn't really be used, just handy to poke the internals quick
+    BinaryOperator<A> combiner = collector.combiner();
+    Function<A, R> finisher = collector.finisher();
+
+    A a1 = supplier.get();
+
+    accumulator.accept(a1, item);
+
+    R actual = finisher.apply(a1);
+    // normal test
+    assertTrue(equals, expected, actual);
+    // these shouldn't really be used, just handy to poke the internals quick
+    actual = finisher.apply(combiner.apply(a1, supplier.get()));
+    assertTrue(equals, expected, actual);
+    actual = finisher.apply(combiner.apply(supplier.get(), a1));
+    assertTrue(equals, expected, actual);
+  }
+
+  private static <T, U> void assertTrue(BiPredicate<T, U> predicate, T expected, U actual) {
+    assertTrue("expected= " + expected + ", actual=" + actual, predicate.test(expected, actual));
+  }
+
+}
