< prev index next >

src/java.base/share/classes/java/util/stream/Collectors.java

Print this page
rev 53968 : enable Collector pre-sizing
rev 53969 : added map loadfactor and collector nullchecks

@@ -43,20 +43,11 @@
 import java.util.Optional;
 import java.util.Set;
 import java.util.StringJoiner;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
-import java.util.function.BiConsumer;
-import java.util.function.BiFunction;
-import java.util.function.BinaryOperator;
-import java.util.function.Consumer;
-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;
+import java.util.function.*;
 
 /**
  * Implementations of {@link Collector} that implement various useful reduction
  * operations, such as accumulating elements into collections, summarizing
  * elements according to various criteria, etc.

@@ -191,28 +182,47 @@
      *
      * @param <T> the type of elements to be collected
      * @param <R> the type of the result
      */
     static class CollectorImpl<T, A, R> implements Collector<T, A, R> {
+        private final IntFunction<A> sizedSupplier;
         private final Supplier<A> supplier;
         private final BiConsumer<A, T> accumulator;
         private final BinaryOperator<A> combiner;
         private final Function<A, R> finisher;
         private final Set<Characteristics> characteristics;
 
-        CollectorImpl(Supplier<A> supplier,
+        CollectorImpl(IntFunction<A> sizedSupplier,
+                      Supplier<A> supplier,
                       BiConsumer<A, T> accumulator,
                       BinaryOperator<A> combiner,
                       Function<A,R> finisher,
                       Set<Characteristics> characteristics) {
+            this.sizedSupplier = sizedSupplier;
             this.supplier = supplier;
             this.accumulator = accumulator;
             this.combiner = combiner;
             this.finisher = finisher;
             this.characteristics = characteristics;
         }
 
+        CollectorImpl(IntFunction<A> sizedSupplier,
+                      Supplier<A> supplier,
+                      BiConsumer<A, T> accumulator,
+                      BinaryOperator<A> combiner,
+                      Set<Characteristics> characteristics) {
+            this(sizedSupplier, supplier, accumulator, combiner, castingIdentity(), characteristics);
+        }
+
+        CollectorImpl(Supplier<A> supplier,
+                      BiConsumer<A, T> accumulator,
+                      BinaryOperator<A> combiner,
+                      Function<A,R> finisher,
+                      Set<Characteristics> characteristics) {
+            this(ignored -> supplier.get(), supplier, accumulator, combiner, finisher, characteristics);
+        }
+
         CollectorImpl(Supplier<A> supplier,
                       BiConsumer<A, T> accumulator,
                       BinaryOperator<A> combiner,
                       Set<Characteristics> characteristics) {
             this(supplier, accumulator, combiner, castingIdentity(), characteristics);

@@ -227,10 +237,15 @@
         public Supplier<A> supplier() {
             return supplier;
         }
 
         @Override
+        public IntFunction<A> sizedSupplier() {
+            return sizedSupplier;
+        }
+
+        @Override
         public BinaryOperator<A> combiner() {
             return combiner;
         }
 
         @Override

@@ -273,11 +288,13 @@
      * @return a {@code Collector} which collects all the input elements into a
      * {@code List}, in encounter order
      */
     public static <T>
     Collector<T, ?, List<T>> toList() {
-        return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
+        return new CollectorImpl<>((IntFunction<List<T>>) ArrayList::new,
+                                   (Supplier<List<T>>) ArrayList::new,
+                                   List::add,
                                    (left, right) -> { left.addAll(right); return left; },
                                    CH_ID);
     }
 
     /**

@@ -292,11 +309,13 @@
      * @since 10
      */
     @SuppressWarnings("unchecked")
     public static <T>
     Collector<T, ?, List<T>> toUnmodifiableList() {
-        return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
+        return new CollectorImpl<>((IntFunction<List<T>>) ArrayList::new,
+                                   (Supplier<List<T>>) ArrayList::new,
+                                   List::add,
                                    (left, right) -> { left.addAll(right); return left; },
                                    list -> (List<T>)List.of(list.toArray()),
                                    CH_NOID);
     }
 

@@ -455,11 +474,11 @@
      */
     public static <T, U, A, R>
     Collector<T, ?, R> mapping(Function<? super T, ? extends U> mapper,
                                Collector<? super U, A, R> downstream) {
         BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator();
-        return new CollectorImpl<>(downstream.supplier(),
+        return new CollectorImpl<>(downstream.sizedSupplier(), downstream.supplier(),
                                    (r, t) -> downstreamAccumulator.accept(r, mapper.apply(t)),
                                    downstream.combiner(), downstream.finisher(),
                                    downstream.characteristics());
     }
 

@@ -591,11 +610,12 @@
                 characteristics = EnumSet.copyOf(characteristics);
                 characteristics.remove(Collector.Characteristics.IDENTITY_FINISH);
                 characteristics = Collections.unmodifiableSet(characteristics);
             }
         }
-        return new CollectorImpl<>(downstream.supplier(),
+        return new CollectorImpl<>(downstream.sizedSupplier(),
+                                   downstream.supplier(),
                                    downstream.accumulator(),
                                    downstream.combiner(),
                                    downstream.finisher().andThen(finisher),
                                    characteristics);
     }

@@ -1454,11 +1474,12 @@
      * @see #toConcurrentMap(Function, Function)
      */
     public static <T, K, U>
     Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
                                     Function<? super T, ? extends U> valueMapper) {
-        return new CollectorImpl<>(HashMap::new,
+        return new CollectorImpl<>(size -> new HashMap<>((int) Math.ceil(size / .75), .75f),
+                                   HashMap::new,
                                    uniqKeysMapAccumulator(keyMapper, valueMapper),
                                    uniqKeysMapMerger(),
                                    CH_ID);
     }
 

@@ -1713,11 +1734,12 @@
      * @see #toConcurrentMap(Function, Function, BinaryOperator, Supplier)
      */
     public static <T, K, U>
     Collector<T, ?, ConcurrentMap<K,U>> toConcurrentMap(Function<? super T, ? extends K> keyMapper,
                                                         Function<? super T, ? extends U> valueMapper) {
-        return new CollectorImpl<>(ConcurrentHashMap::new,
+        return new CollectorImpl<>(size -> new ConcurrentHashMap<>((int) Math.ceil(size / .75), .75f),
+                                   ConcurrentHashMap::new,
                                    uniqKeysMapAccumulator(keyMapper, valueMapper),
                                    uniqKeysMapMerger(),
                                    CH_CONCURRENT_ID);
     }
 

@@ -1931,10 +1953,14 @@
         Objects.requireNonNull(downstream2, "downstream2");
         Objects.requireNonNull(merger, "merger");
 
         Supplier<A1> c1Supplier = Objects.requireNonNull(downstream1.supplier(), "downstream1 supplier");
         Supplier<A2> c2Supplier = Objects.requireNonNull(downstream2.supplier(), "downstream2 supplier");
+        IntFunction<A1> c1SizedSupplier =
+                Objects.requireNonNull(downstream1.sizedSupplier(), "downstream1 sizedSupplier");
+        IntFunction<A2> c2SizedSupplier =
+                Objects.requireNonNull(downstream2.sizedSupplier(), "downstream2 sizedSupplier");
         BiConsumer<A1, ? super T> c1Accumulator =
                 Objects.requireNonNull(downstream1.accumulator(), "downstream1 accumulator");
         BiConsumer<A2, ? super T> c2Accumulator =
                 Objects.requireNonNull(downstream2.accumulator(), "downstream2 accumulator");
         BinaryOperator<A1> c1Combiner = Objects.requireNonNull(downstream1.combiner(), "downstream1 combiner");

@@ -1954,12 +1980,22 @@
             c.remove(Collector.Characteristics.IDENTITY_FINISH);
             characteristics = Collections.unmodifiableSet(c);
         }
 
         class PairBox {
-            A1 left = c1Supplier.get();
-            A2 right = c2Supplier.get();
+            A1 left;
+            A2 right;
+
+            PairBox(int initialSize) {
+                left = c1SizedSupplier.apply(initialSize);
+                right = c2SizedSupplier.apply(initialSize);
+            }
+
+            PairBox() {
+                left = c1Supplier.get();
+                right = c2Supplier.get();
+            }
 
             void add(T t) {
                 c1Accumulator.accept(left, t);
                 c2Accumulator.accept(right, t);
             }

@@ -1975,11 +2011,16 @@
                 R2 r2 = c2Finisher.apply(right);
                 return merger.apply(r1, r2);
             }
         }
 
-        return new CollectorImpl<>(PairBox::new, PairBox::add, PairBox::combine, PairBox::get, characteristics);
+        return new CollectorImpl<>(PairBox::new,
+                                   PairBox::new,
+                                   PairBox::add,
+                                   PairBox::combine,
+                                   PairBox::get,
+                                   characteristics);
     }
 
     /**
      * Implementation class used by partitioningBy.
      */
< prev index next >