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

Print this page
rev 7923 : 8023681: Fix raw type warning caused by Sink
Reviewed-by:


 120             = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED,
 121                                                      Collector.Characteristics.IDENTITY_FINISH));
 122     static final Set<Collector.Characteristics> CH_NOID = Collections.emptySet();
 123 
 124     private Collectors() { }
 125 
 126     /**
 127      * Returns a merge function, suitable for use in
 128      * {@link Map#merge(Object, Object, BiFunction) Map.merge()} or
 129      * {@link #toMap(Function, Function, BinaryOperator) toMap()}, which always
 130      * throws {@code IllegalStateException}.  This can be used to enforce the
 131      * assumption that the elements being collected are distinct.
 132      *
 133      * @param <T> the type of input arguments to the merge function
 134      * @return a merge function which always throw {@code IllegalStateException}
 135      */
 136     private static <T> BinaryOperator<T> throwingMerger() {
 137         return (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); };
 138     }
 139 





 140     /**
 141      * Simple implementation class for {@code Collector}.
 142      *
 143      * @param <T> the type of elements to be collected
 144      * @param <R> the type of the result
 145      */
 146     static class CollectorImpl<T, A, R> implements Collector<T, A, R> {
 147         private final Supplier<A> supplier;
 148         private final BiConsumer<A, T> accumulator;
 149         private final BinaryOperator<A> combiner;
 150         private final Function<A, R> finisher;
 151         private final Set<Characteristics> characteristics;
 152 
 153         CollectorImpl(Supplier<A> supplier,
 154                       BiConsumer<A, T> accumulator,
 155                       BinaryOperator<A> combiner,
 156                       Function<A,R> finisher,
 157                       Set<Characteristics> characteristics) {
 158             this.supplier = supplier;
 159             this.accumulator = accumulator;
 160             this.combiner = combiner;
 161             this.finisher = finisher;
 162             this.characteristics = characteristics;
 163         }
 164 
 165         CollectorImpl(Supplier<A> supplier,
 166                       BiConsumer<A, T> accumulator,
 167                       BinaryOperator<A> combiner,
 168                       Set<Characteristics> characteristics) {
 169             this(supplier, accumulator, combiner, i -> (R) i, characteristics);
 170         }
 171 
 172         @Override
 173         public BiConsumer<A, T> accumulator() {
 174             return accumulator;
 175         }
 176 
 177         @Override
 178         public Supplier<A> supplier() {
 179             return supplier;
 180         }
 181 
 182         @Override
 183         public BinaryOperator<A> combiner() {
 184             return combiner;
 185         }
 186 
 187         @Override
 188         public Function<A, R> finisher() {
 189             return finisher;


 192         @Override
 193         public Set<Characteristics> characteristics() {
 194             return characteristics;
 195         }
 196     }
 197 
 198     /**
 199      * Returns a {@code Collector} that accumulates the input elements into a
 200      * new {@code Collection}, in encounter order.  The {@code Collection} is
 201      * created by the provided factory.
 202      *
 203      * @param <T> the type of the input elements
 204      * @param <C> the type of the resulting {@code Collection}
 205      * @param collectionFactory a {@code Supplier} which returns a new, empty
 206      * {@code Collection} of the appropriate type
 207      * @return a {@code Collector} which collects all the input elements into a
 208      * {@code Collection}, in encounter order
 209      */
 210     public static <T, C extends Collection<T>>
 211     Collector<T, ?, C> toCollection(Supplier<C> collectionFactory) {
 212         return new CollectorImpl<>(collectionFactory, Collection::add,
 213                                    (r1, r2) -> { r1.addAll(r2); return r1; },
 214                                    CH_ID);
 215     }
 216 
 217     /**
 218      * Returns a {@code Collector} that accumulates the input elements into a
 219      * new {@code List}. There are no guarantees on the type, mutability,
 220      * serializability, or thread-safety of the {@code List} returned.
 221      *
 222      * @param <T> the type of the input elements
 223      * @return a {@code Collector} which collects all the input elements into a
 224      * {@code List}, in encounter order
 225      */
 226     public static <T>
 227     Collector<T, ?, List<T>> toList() {
 228         return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
 229                                    (left, right) -> { left.addAll(right); return left; },
 230                                    CH_ID);
 231     }
 232 


1029      * {@code Map<Boolean, D>} whose values are the result of the downstream
1030      * reduction.
1031      *
1032      * <p>There are no guarantees on the type, mutability,
1033      * serializability, or thread-safety of the {@code Map} returned.
1034      *
1035      * @param <T> the type of the input elements
1036      * @param <A> the intermediate accumulation type of the downstream collector
1037      * @param <D> the result type of the downstream reduction
1038      * @param predicate a predicate used for classifying input elements
1039      * @param downstream a {@code Collector} implementing the downstream
1040      *                   reduction
1041      * @return a {@code Collector} implementing the cascaded partitioning
1042      *         operation
1043      *
1044      * @see #partitioningBy(Predicate)
1045      */
1046     public static <T, D, A>
1047     Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate,
1048                                                     Collector<? super T, A, D> downstream) {
1049         @SuppressWarnings("unchecked")
1050         BiConsumer<D, ? super T> downstreamAccumulator = (BiConsumer<D, ? super T>) downstream.accumulator();
1051         BiConsumer<Map<Boolean, A>, T> accumulator = (result, t) -> {
1052             Partition<D> asPartition = ((Partition<D>) result);
1053             downstreamAccumulator.accept(predicate.test(t) ? asPartition.forTrue : asPartition.forFalse, t);
1054         };
1055         BinaryOperator<A> op = downstream.combiner();
1056         BinaryOperator<Map<Boolean, A>> merger = (m1, m2) -> {
1057             Partition<A> left = (Partition<A>) m1;
1058             Partition<A> right = (Partition<A>) m2;
1059             return new Partition<>(op.apply(left.forTrue, right.forTrue),
1060                                    op.apply(left.forFalse, right.forFalse));
1061         };
1062         Supplier<Map<Boolean, A>> supplier = () -> new Partition<>(downstream.supplier().get(),
1063                                                                    downstream.supplier().get());
1064         if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
1065             return new CollectorImpl<>(supplier, accumulator, merger, CH_ID);
1066         }
1067         else {
1068             Function<Map<Boolean, A>, Map<Boolean, D>> finisher = (Map<Boolean, A> par) -> {
1069                 Partition<A> asAPartition = (Partition<A>) par;
1070                 return new Partition<>(downstream.finisher().apply(asAPartition.forTrue),
1071                                        downstream.finisher().apply(asAPartition.forFalse));
1072             };
1073             return new CollectorImpl<>(supplier, accumulator, merger, finisher, CH_NOID);
1074         }
1075     }
1076 
1077     /**
1078      * Returns a {@code Collector} that accumulate elements into a
1079      * {@code Map} whose keys and values are the result of applying the provided
1080      * mapping functions to the input elements.
1081      *
1082      * <p>If the mapped keys contains duplicates (according to
1083      * {@link Object#equals(Object)}), an {@code IllegalStateException} is
1084      * thrown when the collection operation is performed.  If the mapped keys
1085      * may have duplicates, use {@link #toMap(Function, Function, BinaryOperator)}
1086      * instead.
1087      *
1088      * @apiNote
1089      * It is common for either the key or the value to be the input elements.
1090      * In this case, the utility method
1091      * {@link java.util.function.Function#identity()} may be helpful.
1092      * For example, the following produces a {@code Map} mapping




 120             = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED,
 121                                                      Collector.Characteristics.IDENTITY_FINISH));
 122     static final Set<Collector.Characteristics> CH_NOID = Collections.emptySet();
 123 
 124     private Collectors() { }
 125 
 126     /**
 127      * Returns a merge function, suitable for use in
 128      * {@link Map#merge(Object, Object, BiFunction) Map.merge()} or
 129      * {@link #toMap(Function, Function, BinaryOperator) toMap()}, which always
 130      * throws {@code IllegalStateException}.  This can be used to enforce the
 131      * assumption that the elements being collected are distinct.
 132      *
 133      * @param <T> the type of input arguments to the merge function
 134      * @return a merge function which always throw {@code IllegalStateException}
 135      */
 136     private static <T> BinaryOperator<T> throwingMerger() {
 137         return (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); };
 138     }
 139 
 140     @SuppressWarnings("unchecked")
 141     private static <I, R> Function<I, R> castingIdentity() {
 142         return i -> (R) i;
 143     }
 144 
 145     /**
 146      * Simple implementation class for {@code Collector}.
 147      *
 148      * @param <T> the type of elements to be collected
 149      * @param <R> the type of the result
 150      */
 151     static class CollectorImpl<T, A, R> implements Collector<T, A, R> {
 152         private final Supplier<A> supplier;
 153         private final BiConsumer<A, T> accumulator;
 154         private final BinaryOperator<A> combiner;
 155         private final Function<A, R> finisher;
 156         private final Set<Characteristics> characteristics;
 157 
 158         CollectorImpl(Supplier<A> supplier,
 159                       BiConsumer<A, T> accumulator,
 160                       BinaryOperator<A> combiner,
 161                       Function<A,R> finisher,
 162                       Set<Characteristics> characteristics) {
 163             this.supplier = supplier;
 164             this.accumulator = accumulator;
 165             this.combiner = combiner;
 166             this.finisher = finisher;
 167             this.characteristics = characteristics;
 168         }
 169 
 170         CollectorImpl(Supplier<A> supplier,
 171                       BiConsumer<A, T> accumulator,
 172                       BinaryOperator<A> combiner,
 173                       Set<Characteristics> characteristics) {
 174             this(supplier, accumulator, combiner, castingIdentity(), characteristics);
 175         }
 176 
 177         @Override
 178         public BiConsumer<A, T> accumulator() {
 179             return accumulator;
 180         }
 181 
 182         @Override
 183         public Supplier<A> supplier() {
 184             return supplier;
 185         }
 186 
 187         @Override
 188         public BinaryOperator<A> combiner() {
 189             return combiner;
 190         }
 191 
 192         @Override
 193         public Function<A, R> finisher() {
 194             return finisher;


 197         @Override
 198         public Set<Characteristics> characteristics() {
 199             return characteristics;
 200         }
 201     }
 202 
 203     /**
 204      * Returns a {@code Collector} that accumulates the input elements into a
 205      * new {@code Collection}, in encounter order.  The {@code Collection} is
 206      * created by the provided factory.
 207      *
 208      * @param <T> the type of the input elements
 209      * @param <C> the type of the resulting {@code Collection}
 210      * @param collectionFactory a {@code Supplier} which returns a new, empty
 211      * {@code Collection} of the appropriate type
 212      * @return a {@code Collector} which collects all the input elements into a
 213      * {@code Collection}, in encounter order
 214      */
 215     public static <T, C extends Collection<T>>
 216     Collector<T, ?, C> toCollection(Supplier<C> collectionFactory) {
 217         return new CollectorImpl<>(collectionFactory, Collection<T>::add,
 218                                    (r1, r2) -> { r1.addAll(r2); return r1; },
 219                                    CH_ID);
 220     }
 221 
 222     /**
 223      * Returns a {@code Collector} that accumulates the input elements into a
 224      * new {@code List}. There are no guarantees on the type, mutability,
 225      * serializability, or thread-safety of the {@code List} returned.
 226      *
 227      * @param <T> the type of the input elements
 228      * @return a {@code Collector} which collects all the input elements into a
 229      * {@code List}, in encounter order
 230      */
 231     public static <T>
 232     Collector<T, ?, List<T>> toList() {
 233         return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
 234                                    (left, right) -> { left.addAll(right); return left; },
 235                                    CH_ID);
 236     }
 237 


1034      * {@code Map<Boolean, D>} whose values are the result of the downstream
1035      * reduction.
1036      *
1037      * <p>There are no guarantees on the type, mutability,
1038      * serializability, or thread-safety of the {@code Map} returned.
1039      *
1040      * @param <T> the type of the input elements
1041      * @param <A> the intermediate accumulation type of the downstream collector
1042      * @param <D> the result type of the downstream reduction
1043      * @param predicate a predicate used for classifying input elements
1044      * @param downstream a {@code Collector} implementing the downstream
1045      *                   reduction
1046      * @return a {@code Collector} implementing the cascaded partitioning
1047      *         operation
1048      *
1049      * @see #partitioningBy(Predicate)
1050      */
1051     public static <T, D, A>
1052     Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate,
1053                                                     Collector<? super T, A, D> downstream) {
1054         BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
1055         BiConsumer<Partition<A>, T> accumulator = (result, t) ->
1056                 downstreamAccumulator.accept(predicate.test(t) ? result.forTrue : result.forFalse, t);



1057         BinaryOperator<A> op = downstream.combiner();
1058         BinaryOperator<Partition<A>> merger = (left, right) ->
1059                 new Partition<>(op.apply(left.forTrue, right.forTrue),


1060                                 op.apply(left.forFalse, right.forFalse));
1061         Supplier<Partition<A>> supplier = () ->
1062                 new Partition<>(downstream.supplier().get(),
1063                                 downstream.supplier().get());
1064         if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
1065             return new CollectorImpl<>(supplier, accumulator, merger, CH_ID);
1066         }
1067         else {
1068             Function<Partition<A>, Map<Boolean, D>> finisher = par ->
1069                     new Partition<>(downstream.finisher().apply(par.forTrue),
1070                                     downstream.finisher().apply(par.forFalse));


1071             return new CollectorImpl<>(supplier, accumulator, merger, finisher, CH_NOID);
1072         }
1073     }
1074 
1075     /**
1076      * Returns a {@code Collector} that accumulate elements into a
1077      * {@code Map} whose keys and values are the result of applying the provided
1078      * mapping functions to the input elements.
1079      *
1080      * <p>If the mapped keys contains duplicates (according to
1081      * {@link Object#equals(Object)}), an {@code IllegalStateException} is
1082      * thrown when the collection operation is performed.  If the mapped keys
1083      * may have duplicates, use {@link #toMap(Function, Function, BinaryOperator)}
1084      * instead.
1085      *
1086      * @apiNote
1087      * It is common for either the key or the value to be the input elements.
1088      * In this case, the utility method
1089      * {@link java.util.function.Function#identity()} may be helpful.
1090      * For example, the following produces a {@code Map} mapping