• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

amaembo / streamex / #683

09 Aug 2025 05:15PM UTC coverage: 99.725% (+0.05%) from 99.673%
#683

push

amaembo
Update workflow versions in test.yml

5804 of 5820 relevant lines covered (99.73%)

1.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.77
/src/main/java/one/util/streamex/MoreCollectors.java
1
/*
2
 * Copyright 2015, 2024 StreamEx contributors
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package one.util.streamex;
17

18
import org.jspecify.annotations.NullMarked;
19
import org.jspecify.annotations.Nullable;
20

21
import java.util.*;
22
import java.util.Map.Entry;
23
import java.util.function.*;
24
import java.util.stream.Collector;
25
import java.util.stream.Collector.Characteristics;
26
import java.util.stream.Collectors;
27
import java.util.stream.Stream;
28

29
import static one.util.streamex.AbstractStreamEx.addToMap;
30
import static one.util.streamex.Internals.*;
31

32
/**
33
 * Implementations of several collectors in addition to ones available in JDK.
34
 * 
35
 * @author Tagir Valeev
36
 * @see Collectors
37
 * @see Joining
38
 * @since 0.3.2
39
 */
40
@NullMarked
41
public final class MoreCollectors {
42
    private MoreCollectors() {
1✔
43
        throw new UnsupportedOperationException();
1✔
44
    }
45

46
    /**
47
     * Returns a {@code Collector} which just ignores the input and calls the
48
     * provided supplier once to return the output.
49
     * 
50
     * @param <T> the type of input elements
51
     * @param <U> the type of output
52
     * @param supplier the supplier of the output
53
     * @return a {@code Collector} which just ignores the input and calls the
54
     *         provided supplier once to return the output.
55
     */
56
    private static <T extends @Nullable Object, U extends @Nullable Object> Collector<T, ?, U> empty(
57
            Supplier<U> supplier) {
58
        return new CancellableCollectorImpl<>(() -> NONE, (acc, t) -> {
1✔
59
            // empty
60
        }, selectFirst(), acc -> supplier.get(), alwaysTrue(), EnumSet.of(Characteristics.UNORDERED,
1✔
61
            Characteristics.CONCURRENT));
62
    }
63

64
    private static <T extends @Nullable Object> Collector<T, ?, List<T>> empty() {
65
        return empty(ArrayList::new);
1✔
66
    }
67

68
    /**
69
     * Returns a {@code Collector} that accumulates the input elements into a
70
     * new array.
71
     *
72
     * <p>
73
     * The operation performed by the returned collector is equivalent to
74
     * {@code stream.toArray(generator)}. This collector is mostly useful as a
75
     * downstream collector.
76
     *
77
     * @param <T> the type of the input elements
78
     * @param generator a function which produces a new array of the desired
79
     *        type and the provided length
80
     * @return a {@code Collector} which collects all the input elements into an
81
     *         array, in encounter order
82
     * @throws NullPointerException if generator is null.
83
     */
84
    public static <T extends @Nullable Object> Collector<T, ?, T[]> toArray(IntFunction<T[]> generator) {
85
        Objects.requireNonNull(generator);
1✔
86
        return Collectors.collectingAndThen(Collectors.toList(), list -> list.toArray(generator.apply(list.size())));
1✔
87
    }
88

89
    /**
90
     * Returns a {@code Collector} which produces a boolean array containing the
91
     * results of applying the given predicate to the input elements, in
92
     * encounter order.
93
     * 
94
     * @param <T> the type of the input elements
95
     * @param predicate a non-interfering, stateless predicate to apply to each
96
     *        input element. The result values of this predicate are collected
97
     *        to the resulting boolean array.
98
     * @return a {@code Collector} which collects the results of the predicate
99
     *         function to the boolean array, in encounter order.
100
     * @throws NullPointerException if predicate is null.
101
     * @since 0.3.8
102
     */
103
    public static <T extends @Nullable Object> Collector<T, ?, boolean[]> toBooleanArray(Predicate<? super T> predicate) {
104
        Objects.requireNonNull(predicate);
1✔
105
        return PartialCollector.booleanArray().asRef((box, t) -> {
1✔
106
            if (predicate.test(t))
1✔
107
                box.a.set(box.b);
1✔
108
            box.b = StrictMath.addExact(box.b, 1);
1✔
109
        });
1✔
110
    }
111

112
    /**
113
     * Returns a {@code Collector} that accumulates the input enum values into a
114
     * new {@code EnumSet}.
115
     *
116
     * <p>
117
     * This method returns a
118
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
119
     * collector</a>: it may not process all the elements if the resulting set
120
     * contains all possible enum values.
121
     * 
122
     * @param <T> the type of the input elements
123
     * @param enumClass the class of input enum values
124
     * @return a {@code Collector} which collects all the input elements into a
125
     *         {@code EnumSet}
126
     * @throws NullPointerException if enumClass is null.
127
     */
128
    public static <T extends Enum<T>> Collector<T, ?, EnumSet<T>> toEnumSet(Class<T> enumClass) {
129
        int size = EnumSet.allOf(enumClass).size();
1✔
130
        return new CancellableCollectorImpl<>(() -> EnumSet.noneOf(enumClass), EnumSet::add, (s1, s2) -> {
1✔
131
            s1.addAll(s2);
1✔
132
            return s1;
1✔
133
        }, Function.identity(), set -> set.size() == size, UNORDERED_ID_CHARACTERISTICS);
1✔
134
    }
135

136
    /**
137
     * Returns a {@code Collector} that accumulates elements into a {@code Map}
138
     * whose keys and values are taken from {@code Map.Entry}.
139
     *
140
     * <p>
141
     * There are no guarantees on the type or serializability of the {@code Map} returned;
142
     * if more control over the returned {@code Map} is required, use {@link #entriesToCustomMap(Supplier)}
143
     *
144
     * <p>
145
     * Returned {@code Map} is guaranteed to be modifiable. See {@link one.util.streamex.EntryStream#toMap()}.
146
     *
147
     * @param <K> the type of the map keys
148
     * @param <V> the type of the map values
149
     * @return {@code Collector} which collects elements into a {@code Map}
150
     * whose keys and values are taken from {@code Map.Entry}
151
     * @throws IllegalStateException if this stream contains duplicate keys
152
     *                               (according to {@link Object#equals(Object)}).
153
     * @see #entriesToMap(BinaryOperator)
154
     * @see Collectors#toMap(Function, Function)
155
     * @since 0.7.3
156
     */
157
    public static <K extends @Nullable Object, V extends @Nullable Object> Collector<Entry<? extends K, ? extends V>, ?, Map<K, V>> entriesToMap() {
158
        return entriesToCustomMap(HashMap::new);
1✔
159
    }
160

161
    /**
162
     * Returns a {@code Collector} that accumulates elements into a {@code Map}
163
     * whose keys and values are taken from {@code Map.Entry} and combining them
164
     * using the provided {@code combiner} function to the input elements.
165
     *
166
     * <p>
167
     * There are no guarantees on the type or serializability of the {@code Map} returned;
168
     * if more control over the returned {@code Map} is required, use {@link #entriesToCustomMap(BinaryOperator, Supplier)}
169
     *
170
     * <p>
171
     * Returned {@code Map} is guaranteed to be modifiable. See {@link one.util.streamex.EntryStream#toMap()}.
172
     *
173
     * <p>If the mapped keys contains duplicates (according to {@link Object#equals(Object)}),
174
     * the value mapping function is applied to each equal element, and the
175
     * results are merged using the provided {@code combiner} function.
176
     *
177
     * @param <K>      the type of the map keys
178
     * @param <V>      the type of the map values
179
     * @param combiner a merge function, used to resolve collisions between
180
     *                 values associated with the same key, as supplied
181
     *                 to {@link Map#merge(Object, Object, BiFunction)}
182
     * @return {@code Collector} which collects elements into a {@code Map}
183
     * whose keys and values are taken from {@code Map.Entry} and combining them
184
     * using the {@code combiner} function
185
     * @throws NullPointerException if combiner is null.
186
     * @see #entriesToMap()
187
     * @see Collectors#toMap(Function, Function, BinaryOperator)
188
     * @since 0.7.3
189
     */
190
    public static <K extends @Nullable Object, V extends @Nullable Object> Collector<Entry<? extends K, ? extends V>, ?, Map<K, V>> entriesToMap(
191
            BinaryOperator<V> combiner) {
192
        return entriesToCustomMap(combiner, HashMap::new);
1✔
193
    }
194

195
    /**
196
     * Returns a {@code Collector} that accumulates elements into
197
     * a result {@code Map} defined by {@code mapSupplier} function
198
     * whose keys and values are taken from {@code Map.Entry}.
199
     *
200
     * @param <K> the type of the map keys
201
     * @param <V> the type of the map values
202
     * @param <M> the type of the resulting {@code Map}
203
     * @param mapSupplier a function which returns a new, empty {@code Map} into
204
     *                    which the results will be inserted
205
     * @return {@code Collector} which collects elements into a {@code Map}
206
     * defined by {@code mapSupplier} function
207
     * whose keys and values are taken from {@code Map.Entry}
208
     * @throws IllegalStateException if this stream contains duplicate keys
209
     *                               (according to {@link Object#equals(Object)}).
210
     * @throws NullPointerException  if mapSupplier is null.
211
     * @throws NullPointerException  if entry value is null.
212
     * @see #entriesToCustomMap(BinaryOperator, Supplier)
213
     * @see Collector#of(Supplier, BiConsumer, BinaryOperator, Collector.Characteristics...)
214
     * @since 0.7.3
215
     */
216
    public static <
217
            K extends @Nullable Object,
218
            V,
219
            M extends Map<K, V>> Collector<Entry<? extends K, ? extends V>, ?, M> entriesToCustomMap(
220
            Supplier<M> mapSupplier) {
221
        return Collector.of(mapSupplier,
1✔
222
                (m, entry) -> addToMap(m, entry.getKey(), Objects.requireNonNull(entry.getValue())),
1✔
223
                (m1, m2) -> {
224
                    m2.forEach((k, v) -> addToMap(m1, k, v));
1✔
225
                    return m1;
1✔
226
                }
227
        );
228
    }
229

230
    /**
231
     * Returns a {@code Collector} that accumulates elements into
232
     * a result {@code Map} defined by {@code mapSupplier} function
233
     * whose keys and values are taken from {@code Map.Entry} and combining them
234
     * using the provided {@code combiner} function to the input elements.
235
     *
236
     * <p>If the mapped keys contains duplicates (according to {@link Object#equals(Object)}),
237
     * the value mapping function is applied to each equal element, and the
238
     * results are merged using the provided {@code combiner} function.
239
     *
240
     * @param <K>         the type of the map keys
241
     * @param <V>         the type of the map values
242
     * @param <M>         the type of the resulting {@code Map}
243
     * @param combiner    a merge function, used to resolve collisions between
244
     *                    values associated with the same key, as supplied
245
     *                    to {@link Map#merge(Object, Object, BiFunction)}
246
     * @param mapSupplier a function which returns a new, empty {@code Map} into
247
     *                    which the results will be inserted
248
     * @return {@code Collector} which collects elements into a {@code Map}
249
     * whose keys and values are taken from {@code Map.Entry} and combining them
250
     * using the {@code combiner} function
251
     * @throws NullPointerException if {@code combiner} is null.
252
     * @throws NullPointerException if {@code mapSupplier} is null.
253
     * @see #entriesToCustomMap(Supplier)
254
     * @see Collectors#toMap(Function, Function, BinaryOperator, Supplier)
255
     * @since 0.7.3
256
     */
257
    public static <
258
            K extends @Nullable Object,
259
            V extends @Nullable Object,
260
            M extends Map<K, V>> Collector<Entry<? extends K, ? extends V>, ?, M> entriesToCustomMap(
261
            BinaryOperator<V> combiner, Supplier<M> mapSupplier) {
262
        Objects.requireNonNull(combiner);
1✔
263
        Objects.requireNonNull(mapSupplier);
1✔
264
        return Collectors.toMap(Entry::getKey, Entry::getValue, combiner, mapSupplier);
1✔
265
    }
266

267
    /**
268
     * Returns a {@code Collector} which counts a number of distinct values the
269
     * mapper function returns for the stream elements.
270
     * 
271
     * <p>
272
     * The operation performed by the returned collector is equivalent to
273
     * {@code stream.map(mapper).distinct().count()}. This collector is mostly
274
     * useful as a downstream collector.
275
     * 
276
     * @param <T> the type of the input elements
277
     * @param mapper a function which classifies input elements.
278
     * @return a collector which counts a number of distinct classes the mapper
279
     *         function returns for the stream elements.
280
     * @throws NullPointerException if mapper is null.
281
     */
282
    public static <T extends @Nullable Object> Collector<T, ?, Integer> distinctCount(Function<? super T, ?> mapper) {
283
        Objects.requireNonNull(mapper);
1✔
284
        return Collectors.collectingAndThen(Collectors.mapping(mapper, Collectors.toSet()), Set::size);
1✔
285
    }
286

287
    /**
288
     * Returns a {@code Collector} which collects into the {@link List} the
289
     * input elements for which given mapper function returns distinct results.
290
     *
291
     * <p>
292
     * For ordered source the order of collected elements is preserved. If the
293
     * same result is returned by mapper function for several elements, only the
294
     * first element is included into the resulting list.
295
     * 
296
     * <p>
297
     * There are no guarantees on the type, mutability, serializability, or
298
     * thread-safety of the {@code List} returned.
299
     * 
300
     * <p>
301
     * The operation performed by the returned collector is equivalent to
302
     * {@code stream.distinct(mapper).toList()}, but may work faster.
303
     * 
304
     * @param <T> the type of the input elements
305
     * @param mapper a function which classifies input elements.
306
     * @return a collector which collects distinct elements to the {@code List}.
307
     * @throws NullPointerException if mapper is null.
308
     * @since 0.3.8
309
     */
310
    public static <T extends @Nullable Object> Collector<T, ?, List<T>> distinctBy(Function<? super T, ?> mapper) {
311
        Objects.requireNonNull(mapper);
1✔
312
        return Collector.<T, Map<Object, T>, List<T>>of(LinkedHashMap::new, (map, t) -> map.putIfAbsent(mapper.apply(
1✔
313
            t), t), (m1, m2) -> {
314
                for (Entry<Object, T> e : m2.entrySet()) {
1✔
315
                    m1.putIfAbsent(e.getKey(), e.getValue());
1✔
316
                }
1✔
317
                return m1;
1✔
318
            }, map -> new ArrayList<>(map.values()));
1✔
319
    }
320

321
    /**
322
     * Returns a {@code Collector} accepting elements of type {@code T} that
323
     * counts the number of input elements and returns result as {@code Integer}
324
     * . If no elements are present, the result is 0.
325
     *
326
     * @param <T> the type of the input elements
327
     * @return a {@code Collector} that counts the input elements
328
     * @since 0.3.3
329
     * @see Collectors#counting()
330
     */
331
    public static <T extends @Nullable Object> Collector<T, ?, Integer> countingInt() {
332
        return PartialCollector.intSum().asRef((acc, t) -> acc[0]++);
1✔
333
    }
334

335
    /**
336
     * Returns a {@code Collector} which aggregates the results of two supplied
337
     * collectors using the supplied finisher function.
338
     * 
339
     * <p>
340
     * This method returns a
341
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
342
     * collector</a> if both downstream collectors are short-circuiting. The
343
     * collection might stop when both downstream collectors report that the
344
     * collection is complete.
345
     * 
346
     * <p>
347
     * This collector is similar to the {@code teeing} collector available since
348
     * JDK 12. The only difference is that this collector correctly combines 
349
     * short-circuiting collectors.
350
     * 
351
     * @param <T> the type of the input elements
352
     * @param <A1> the intermediate accumulation type of the first collector
353
     * @param <A2> the intermediate accumulation type of the second collector
354
     * @param <R1> the result type of the first collector
355
     * @param <R2> the result type of the second collector
356
     * @param <R> the final result type
357
     * @param c1 the first collector
358
     * @param c2 the second collector
359
     * @param finisher the function which merges two results into the single
360
     *        one.
361
     * @return a {@code Collector} which aggregates the results of two supplied
362
     *         collectors.
363
     * @throws NullPointerException if c1 is null, or c2 is null, or finisher is null.
364
     */
365
    public static <
366
            T extends @Nullable Object,
367
            A1 extends @Nullable Object,
368
            A2 extends @Nullable Object,
369
            R1 extends @Nullable Object,
370
            R2 extends @Nullable Object,
371
            R extends @Nullable Object> Collector<T, ?, R> pairing(
372
            Collector<? super T, A1, R1> c1,
373
            Collector<? super T, A2, R2> c2,
374
            BiFunction<? super R1, ? super R2, ? extends R> finisher) {
375
        Objects.requireNonNull(finisher);
1✔
376
        EnumSet<Characteristics> c = EnumSet.noneOf(Characteristics.class);
1✔
377
        c.addAll(c1.characteristics());
1✔
378
        c.retainAll(c2.characteristics());
1✔
379
        c.remove(Characteristics.IDENTITY_FINISH);
1✔
380

381
        Supplier<A1> c1Supplier = c1.supplier();
1✔
382
        Supplier<A2> c2Supplier = c2.supplier();
1✔
383
        BiConsumer<A1, ? super T> c1Accumulator = c1.accumulator();
1✔
384
        BiConsumer<A2, ? super T> c2Accumulator = c2.accumulator();
1✔
385
        BinaryOperator<A1> c1Combiner = c1.combiner();
1✔
386
        BinaryOperator<A2> c2combiner = c2.combiner();
1✔
387

388
        Supplier<PairBox<A1, A2>> supplier = () -> new PairBox<>(c1Supplier.get(), c2Supplier.get());
1✔
389
        BiConsumer<PairBox<A1, A2>, T> accumulator = (acc, v) -> {
1✔
390
            c1Accumulator.accept(acc.a, v);
1✔
391
            c2Accumulator.accept(acc.b, v);
1✔
392
        };
1✔
393
        BinaryOperator<PairBox<A1, A2>> combiner = (acc1, acc2) -> {
1✔
394
            acc1.a = c1Combiner.apply(acc1.a, acc2.a);
1✔
395
            acc1.b = c2combiner.apply(acc1.b, acc2.b);
1✔
396
            return acc1;
1✔
397
        };
398
        Function<PairBox<A1, A2>, R> resFinisher = acc -> {
1✔
399
            R1 r1 = c1.finisher().apply(acc.a);
1✔
400
            R2 r2 = c2.finisher().apply(acc.b);
1✔
401
            return finisher.apply(r1, r2);
1✔
402
        };
403
        Predicate<A1> c1Finished = finished(c1);
1✔
404
        Predicate<A2> c2Finished = finished(c2);
1✔
405
        if (c1Finished != null && c2Finished != null) {
1✔
406
            Predicate<PairBox<A1, A2>> finished = acc -> c1Finished.test(acc.a) && c2Finished.test(acc.b);
1✔
407
            return new CancellableCollectorImpl<>(supplier, accumulator, combiner, resFinisher, finished, c);
1✔
408
        }
409
        return Collector.of(supplier, accumulator, combiner, resFinisher, c.toArray(new Characteristics[0]));
1✔
410
    }
411

412
    /**
413
     * Returns a {@code Collector} which finds the minimal and maximal element
414
     * according to the supplied comparator, then applies finisher function to
415
     * them producing the final result.
416
     * 
417
     * <p>
418
     * This collector produces stable result for ordered stream: if several
419
     * minimal or maximal elements appear, the collector always selects the
420
     * first encountered.
421
     * 
422
     * <p>
423
     * If there are no input elements, the finisher method is not called and
424
     * empty {@code Optional} is returned. Otherwise the finisher result is
425
     * wrapped into {@code Optional}.
426
     *
427
     * @param <T> the type of the input elements
428
     * @param <R> the type of the result wrapped into {@code Optional}
429
     * @param comparator comparator which is used to find minimal and maximal
430
     *        element
431
     * @param finisher a {@link BiFunction} which takes minimal and maximal
432
     *        element and produces the final result.
433
     * @return a {@code Collector} which finds minimal and maximal elements.
434
     * @throws NullPointerException if comparator is null, finisher is null,
435
     * or finisher returns null.
436
     */
437
    public static <T extends @Nullable Object, R> Collector<T, ?, Optional<R>> minMax(Comparator<? super T> comparator,
438
            BiFunction<? super T, ? super T, ? extends R> finisher) {
439
        Objects.requireNonNull(finisher);
1✔
440
        return pairing(Collectors.minBy(comparator), Collectors.maxBy(comparator),
1✔
441
            (min, max) -> min.isPresent() ? Optional.of(finisher.apply(min.get(), max.get())) : Optional.empty());
1✔
442
    }
443

444
    /**
445
     * Returns a {@code Collector} which finds all the elements which are equal
446
     * to each other and bigger than any other element according to the
447
     * specified {@link Comparator}. The found elements are reduced using the
448
     * specified downstream {@code Collector}.
449
     *
450
     * @param <T> the type of the input elements
451
     * @param <A> the intermediate accumulation type of the downstream collector
452
     * @param <D> the result type of the downstream reduction
453
     * @param comparator a {@code Comparator} to compare the elements
454
     * @param downstream a {@code Collector} implementing the downstream
455
     *        reduction
456
     * @return a {@code Collector} which finds all the maximal elements.
457
     * @throws NullPointerException if comparator is null, or downstream is null.
458
     * @see #maxAll(Comparator)
459
     * @see #maxAll(Collector)
460
     * @see #maxAll()
461
     */
462
    public static <
463
            T extends @Nullable Object,
464
            A extends @Nullable Object,
465
            D extends @Nullable Object> Collector<T, ?, D> maxAll(
466
            Comparator<? super T> comparator,
467
            Collector<? super T, A, D> downstream) {
468
        Objects.requireNonNull(comparator);
1✔
469
        Supplier<A> downstreamSupplier = downstream.supplier();
1✔
470
        BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
1✔
471
        BinaryOperator<A> downstreamCombiner = downstream.combiner();
1✔
472
        Supplier<PairBox<A, T>> supplier = () -> new PairBox<>(downstreamSupplier.get(), none());
1✔
473
        BiConsumer<PairBox<A, T>, T> accumulator = (acc, t) -> {
1✔
474
            if (acc.b == NONE) {
1✔
475
                downstreamAccumulator.accept(acc.a, t);
1✔
476
                acc.b = t;
1✔
477
            } else {
478
                int cmp = comparator.compare(t, acc.b);
1✔
479
                if (cmp > 0) {
1✔
480
                    acc.a = downstreamSupplier.get();
1✔
481
                    acc.b = t;
1✔
482
                }
483
                if (cmp >= 0)
1✔
484
                    downstreamAccumulator.accept(acc.a, t);
1✔
485
            }
486
        };
1✔
487
        BinaryOperator<PairBox<A, T>> combiner = (acc1, acc2) -> {
1✔
488
            if (acc2.b == NONE) {
1✔
489
                return acc1;
1✔
490
            }
491
            if (acc1.b == NONE) {
1✔
492
                return acc2;
1✔
493
            }
494
            int cmp = comparator.compare(acc1.b, acc2.b);
1✔
495
            if (cmp > 0) {
1✔
496
                return acc1;
1✔
497
            }
498
            if (cmp < 0) {
1✔
499
                return acc2;
1✔
500
            }
501
            acc1.a = downstreamCombiner.apply(acc1.a, acc2.a);
1✔
502
            return acc1;
1✔
503
        };
504
        Function<PairBox<A, T>, D> finisher = acc -> downstream.finisher().apply(acc.a);
1✔
505
        return Collector.of(supplier, accumulator, combiner, finisher);
1✔
506
    }
507

508
    /**
509
     * Returns a {@code Collector} which finds all the elements which are equal
510
     * to each other and bigger than any other element according to the
511
     * specified {@link Comparator}. The found elements are collected to
512
     * {@link List}.
513
     *
514
     * @param <T> the type of the input elements
515
     * @param comparator a {@code Comparator} to compare the elements
516
     * @return a {@code Collector} which finds all the maximal elements and
517
     *         collects them to the {@code List}.
518
     * @throws NullPointerException if comparator is null.
519
     * @see #maxAll(Comparator, Collector)
520
     * @see #maxAll()
521
     */
522
    public static <T extends @Nullable Object> Collector<T, ?, List<T>> maxAll(Comparator<? super T> comparator) {
523
        return maxAll(comparator, Collectors.toList());
1✔
524
    }
525

526
    /**
527
     * Returns a {@code Collector} which finds all the elements which are equal
528
     * to each other and bigger than any other element according to the natural
529
     * order. The found elements are reduced using the specified downstream
530
     * {@code Collector}.
531
     *
532
     * @param <T> the type of the input elements
533
     * @param <A> the intermediate accumulation type of the downstream collector
534
     * @param <D> the result type of the downstream reduction
535
     * @param downstream a {@code Collector} implementing the downstream
536
     *        reduction
537
     * @return a {@code Collector} which finds all the maximal elements.
538
     * @throws NullPointerException if downstream is null.
539
     * @see #maxAll(Comparator, Collector)
540
     * @see #maxAll(Comparator)
541
     * @see #maxAll()
542
     */
543
    public static <
544
            T extends Comparable<? super T>,
545
            A extends @Nullable Object,
546
            D extends @Nullable Object> Collector<T, ?, D> maxAll(Collector<T, A, D> downstream) {
547
        return maxAll(Comparator.<T>naturalOrder(), downstream);
1✔
548
    }
549

550
    /**
551
     * Returns a {@code Collector} which finds all the elements which are equal
552
     * to each other and bigger than any other element according to the natural
553
     * order. The found elements are collected to {@link List}.
554
     *
555
     * @param <T> the type of the input elements
556
     * @return a {@code Collector} which finds all the maximal elements and
557
     *         collects them to the {@code List}.
558
     * @see #maxAll(Comparator)
559
     * @see #maxAll(Collector)
560
     */
561
    public static <T extends Comparable<? super T>> Collector<T, ?, List<T>> maxAll() {
562
        return maxAll(Comparator.naturalOrder(), Collectors.toList());
1✔
563
    }
564

565
    /**
566
     * Returns a {@code Collector} which finds all the elements which are equal
567
     * to each other and smaller than any other element according to the
568
     * specified {@link Comparator}. The found elements are reduced using the
569
     * specified downstream {@code Collector}.
570
     *
571
     * @param <T> the type of the input elements
572
     * @param <A> the intermediate accumulation type of the downstream collector
573
     * @param <D> the result type of the downstream reduction
574
     * @param comparator a {@code Comparator} to compare the elements
575
     * @param downstream a {@code Collector} implementing the downstream
576
     *        reduction
577
     * @return a {@code Collector} which finds all the minimal elements.
578
     * @throws NullPointerException if comparator is null, or downstream is null.
579
     * @see #minAll(Comparator)
580
     * @see #minAll(Collector)
581
     * @see #minAll()
582
     */
583
    public static <
584
            T extends @Nullable Object,
585
            A extends @Nullable Object,
586
            D extends @Nullable Object> Collector<T, ?, D> minAll(
587
            Comparator<? super T> comparator, Collector<T, A, D> downstream) {
588
        return maxAll(comparator.reversed(), downstream);
1✔
589
    }
590

591
    /**
592
     * Returns a {@code Collector} which finds all the elements which are equal
593
     * to each other and smaller than any other element according to the
594
     * specified {@link Comparator}. The found elements are collected to
595
     * {@link List}.
596
     *
597
     * @param <T> the type of the input elements
598
     * @param comparator a {@code Comparator} to compare the elements
599
     * @return a {@code Collector} which finds all the minimal elements and
600
     *         collects them to the {@code List}.
601
     * @throws NullPointerException if comparator is null.
602
     * @see #minAll(Comparator, Collector)
603
     * @see #minAll()
604
     */
605
    public static <T extends @Nullable Object> Collector<T, ?, List<T>> minAll(Comparator<? super T> comparator) {
606
        return maxAll(comparator.reversed(), Collectors.toList());
1✔
607
    }
608

609
    /**
610
     * Returns a {@code Collector} which finds all the elements which are equal
611
     * to each other and smaller than any other element according to the natural
612
     * order. The found elements are reduced using the specified downstream
613
     * {@code Collector}.
614
     *
615
     * @param <T> the type of the input elements
616
     * @param <A> the intermediate accumulation type of the downstream collector
617
     * @param <D> the result type of the downstream reduction
618
     * @param downstream a {@code Collector} implementing the downstream
619
     *        reduction
620
     * @return a {@code Collector} which finds all the minimal elements.
621
     * @throws NullPointerException if downstream is null.
622
     * @see #minAll(Comparator, Collector)
623
     * @see #minAll(Comparator)
624
     * @see #minAll()
625
     */
626
    public static <T extends Comparable<? super T>,
627
            A extends @Nullable Object,
628
            D extends @Nullable Object> Collector<T, ?, D> minAll(Collector<T, A, D> downstream) {
629
        return maxAll(Comparator.<T>reverseOrder(), downstream);
1✔
630
    }
631

632
    /**
633
     * Returns a {@code Collector} which finds all the elements which are equal
634
     * to each other and smaller than any other element according to the natural
635
     * order. The found elements are collected to {@link List}.
636
     *
637
     * @param <T> the type of the input elements
638
     * @return a {@code Collector} which finds all the minimal elements and
639
     *         collects them to the {@code List}.
640
     * @see #minAll(Comparator)
641
     * @see #minAll(Collector)
642
     */
643
    public static <T extends Comparable<? super T>> Collector<T, ?, List<T>> minAll() {
644
        return maxAll(Comparator.reverseOrder(), Collectors.toList());
1✔
645
    }
646

647
    /**
648
     * Returns a {@code Collector} which collects the stream element if stream
649
     * contains exactly one element.
650
     * 
651
     * <p>
652
     * This method returns a
653
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
654
     * collector</a>.
655
     * 
656
     * @param <T> the type of the input elements
657
     * @return a collector which returns an {@link Optional} describing the only
658
     *         element of the stream. For empty stream or stream containing more
659
     *         than one element an empty {@code Optional} is returned.
660
     * @throws NullPointerException if the only stream element is null.
661
     * @since 0.4.0
662
     */
663
    public static <T> Collector<T, ?, Optional<T>> onlyOne() {
664
        return new CancellableCollectorImpl<T, Box<Optional<T>>, Optional<T>>(Box::new, (box,
1✔
665
                t) -> box.a = box.a == null ? Optional.of(t) : Optional.empty(), (box1, box2) -> box1.a == null ? box2
1✔
666
                        : box2.a == null ? box1 : new Box<>(Optional.empty()), box -> box.a == null ? Optional.empty()
1✔
667
                                : box.a, box -> box.a != null && !box.a.isPresent(), UNORDERED_CHARACTERISTICS);
1✔
668
    }
669

670
    /**
671
     * Returns a {@code Collector} which collects the stream element satisfying the predicate
672
     * if there is only one such element.
673
     *
674
     * <p>
675
     * This method returns a
676
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
677
     * collector</a>.
678
     *
679
     * @param predicate a predicate to be applied to the stream elements
680
     * @param <T> the type of the input elements
681
     * @return a collector which returns an {@link Optional} describing the only
682
     *         element of the stream satisfying the predicate. If stream contains no elements satisfying the predicate,
683
     *         or more than one such element, an empty {@code Optional} is returned.
684
     * @throws NullPointerException if predicate is null or the only stream element is null.
685
     * @since 0.6.7
686
     */
687
    public static <T> Collector<T, ?, Optional<T>> onlyOne(Predicate<? super T> predicate) {
688
        return filtering(predicate, onlyOne());
1✔
689
    }
690

691
    /**
692
     * Returns a {@code Collector} which collects only the first stream element
693
     * if any.
694
     * 
695
     * <p>
696
     * This method returns a
697
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
698
     * collector</a>.
699
     * 
700
     * <p>
701
     * The operation performed by the returned collector is equivalent to
702
     * {@code stream.findFirst()}. This collector is mostly useful as a
703
     * downstream collector.
704
     * 
705
     * @param <T> the type of the input elements
706
     * @return a collector which returns an {@link Optional} which describes the
707
     *         first element of the stream. For empty stream an empty
708
     *         {@code Optional} is returned.
709
     * @throws NullPointerException if the first stream element is null.
710
     */
711
    public static <T> Collector<T, ?, Optional<T>> first() {
712
        return new CancellableCollectorImpl<>(() -> new Box<T>(none()), (box, t) -> {
1✔
713
            if (box.a == NONE)
1✔
714
                box.a = t;
1✔
715
        }, (box1, box2) -> box1.a == NONE ? box2 : box1, box -> box.a == NONE ? Optional.empty() : Optional.of(box.a),
1✔
716
                box -> box.a != NONE, NO_CHARACTERISTICS);
1✔
717
    }
718

719
    /**
720
     * Returns a {@code Collector} which collects only the last stream element
721
     * if any.
722
     * 
723
     * @param <T> the type of the input elements
724
     * @return a collector which returns an {@link Optional} which describes the
725
     *         last element of the stream. For empty stream an empty
726
     *         {@code Optional} is returned.
727
     * @throws NullPointerException if the last stream element is null.
728
     */
729
    public static <T> Collector<T, ?, Optional<T>> last() {
730
        return Collector.of(() -> new Box<T>(none()), (box, t) -> box.a = t,
1✔
731
            (box1, box2) -> box2.a == NONE ? box1 : box2, box -> box.a == NONE ? Optional.empty() : Optional.of(box.a));
1✔
732
    }
733

734
    /**
735
     * Returns a {@code Collector} which collects at most specified number of
736
     * the first stream elements into the {@link List}.
737
     *
738
     * <p>
739
     * This method returns a
740
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
741
     * collector</a>.
742
     * 
743
     * <p>
744
     * There are no guarantees on the type, mutability, serializability, or
745
     * thread-safety of the {@code List} returned.
746
     * 
747
     * <p>
748
     * The operation performed by the returned collector is equivalent to
749
     * {@code stream.limit(n).collect(Collectors.toList())}. This collector is
750
     * mostly useful as a downstream collector.
751
     * 
752
     * @param <T> the type of the input elements
753
     * @param n maximum number of stream elements to preserve
754
     * @return a collector which returns a {@code List} containing the first n
755
     *         stream elements or less if the stream was shorter.
756
     */
757
    public static <T extends @Nullable Object> Collector<T, ?, List<T>> head(int n) {
758
        if (n <= 0)
1✔
759
            return empty();
1✔
760
        return new CancellableCollectorImpl<>(ArrayList::new, (acc, t) -> {
1✔
761
            if (acc.size() < n)
1✔
762
                acc.add(t);
1✔
763
        }, (acc1, acc2) -> {
1✔
764
            acc1.addAll(acc2.subList(0, Math.min(acc2.size(), n - acc1.size())));
1✔
765
            return acc1;
1✔
766
        }, Function.identity(), acc -> acc.size() >= n, ID_CHARACTERISTICS);
1✔
767
    }
768

769
    /**
770
     * Returns a {@code Collector} which collects at most specified number of
771
     * the last stream elements into the {@link List}.
772
     * 
773
     * <p>
774
     * There are no guarantees on the type, mutability, serializability, or
775
     * thread-safety of the {@code List} returned.
776
     * 
777
     * <p>
778
     * When supplied {@code n} is less or equal to zero, this method returns a
779
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
780
     * collector</a> which ignores the input and produces an empty list.
781
     * 
782
     * @param <T> the type of the input elements
783
     * @param n maximum number of stream elements to preserve
784
     * @return a collector which returns a {@code List} containing the last n
785
     *         stream elements or less if the stream was shorter.
786
     */
787
    public static <T extends @Nullable Object> Collector<T, ?, List<T>> tail(int n) {
788
        if (n <= 0)
1✔
789
            return empty();
1✔
790
        return Collector.<T, Deque<T>, List<T>>of(ArrayDeque::new, (acc, t) -> {
1✔
791
            if (acc.size() == n)
1✔
792
                acc.pollFirst();
1✔
793
            acc.addLast(t);
1✔
794
        }, (acc1, acc2) -> {
1✔
795
            while (acc2.size() < n && !acc1.isEmpty()) {
1✔
796
                acc2.addFirst(acc1.pollLast());
1✔
797
            }
798
            return acc2;
1✔
799
        }, ArrayList::new);
800
    }
801

802
    /**
803
     * Returns a {@code Collector} which collects at most specified number of
804
     * the greatest stream elements according to the specified
805
     * {@link Comparator} into the {@link List}. The resulting {@code List} is
806
     * sorted in comparator reverse order (greatest element is the first). The
807
     * order of equal elements is the same as in the input stream.
808
     * 
809
     * <p>
810
     * The operation performed by the returned collector is equivalent to
811
     * {@code stream.sorted(comparator.reversed()).limit(n).collect(Collectors.toList())},
812
     * but usually performed much faster if {@code n} is much less than the
813
     * stream size.
814
     * 
815
     * <p>
816
     * There are no guarantees on the type, mutability, serializability, or
817
     * thread-safety of the {@code List} returned.
818
     * 
819
     * <p>
820
     * When supplied {@code n} is less or equal to zero, this method returns a
821
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
822
     * collector</a> which ignores the input and produces an empty list.
823
     * 
824
     * @param <T> the type of the input elements
825
     * @param comparator the comparator to compare the elements by
826
     * @param n maximum number of stream elements to preserve
827
     * @return a collector which returns a {@code List} containing the greatest
828
     *         n stream elements or less if the stream was shorter.
829
     * @throws NullPointerException if comparator is null.
830
     */
831
    public static <T extends @Nullable Object> Collector<T, ?, List<T>> greatest(Comparator<? super T> comparator, int n) {
832
        return least(comparator.reversed(), n);
1✔
833
    }
834

835
    /**
836
     * Returns a {@code Collector} which collects at most specified number of
837
     * the greatest stream elements according to the natural order into the
838
     * {@link List}. The resulting {@code List} is sorted in reverse order
839
     * (greatest element is the first). The order of equal elements is the same
840
     * as in the input stream.
841
     * 
842
     * <p>
843
     * The operation performed by the returned collector is equivalent to
844
     * {@code stream.sorted(Comparator.reverseOrder()).limit(n).collect(Collectors.toList())},
845
     * but usually performed much faster if {@code n} is much less than the
846
     * stream size.
847
     * 
848
     * <p>
849
     * There are no guarantees on the type, mutability, serializability, or
850
     * thread-safety of the {@code List} returned.
851
     * 
852
     * <p>
853
     * When supplied {@code n} is less or equal to zero, this method returns a
854
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
855
     * collector</a> which ignores the input and produces an empty list.
856
     * 
857
     * @param <T> the type of the input elements
858
     * @param n maximum number of stream elements to preserve
859
     * @return a collector which returns a {@code List} containing the greatest
860
     *         n stream elements or less if the stream was shorter.
861
     */
862
    public static <T extends Comparable<? super T>> Collector<T, ?, List<T>> greatest(int n) {
863
        return least(Comparator.reverseOrder(), n);
1✔
864
    }
865

866
    /**
867
     * Returns a {@code Collector} which collects at most specified number of
868
     * the least stream elements according to the specified {@link Comparator}
869
     * into the {@link List}. The resulting {@code List} is sorted in comparator
870
     * order (least element is the first). The order of equal elements is the
871
     * same as in the input stream.
872
     * 
873
     * <p>
874
     * The operation performed by the returned collector is equivalent to
875
     * {@code stream.sorted(comparator).limit(n).collect(Collectors.toList())},
876
     * but usually performed much faster if {@code n} is much less than the
877
     * stream size.
878
     * 
879
     * <p>
880
     * There are no guarantees on the type, mutability, serializability, or
881
     * thread-safety of the {@code List} returned.
882
     * 
883
     * <p>
884
     * When supplied {@code n} is less or equal to zero, this method returns a
885
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
886
     * collector</a> which ignores the input and produces an empty list.
887
     * 
888
     * @param <T> the type of the input elements
889
     * @param comparator the comparator to compare the elements by
890
     * @param n maximum number of stream elements to preserve
891
     * @return a collector which returns a {@code List} containing the least n
892
     *         stream elements or less if the stream was shorter.
893
     * @throws NullPointerException if comparator is null.
894
     */
895
    public static <T extends @Nullable Object> Collector<T, ?, List<T>> least(Comparator<? super T> comparator, int n) {
896
        Objects.requireNonNull(comparator);
1✔
897
        if (n <= 0)
1✔
898
            return empty();
1✔
899
        if (n == 1) {
1✔
900
            return Collector.of(() -> new Box<T>(none()), (box, t) -> {
1✔
901
                if (box.a == NONE || comparator.compare(t, box.a) < 0)
1✔
902
                    box.a = t;
1✔
903
            }, (box1, box2) -> (box2.a != NONE && (box1.a == NONE || comparator.compare(box2.a, box1.a) < 0)) ? box2
1✔
904
                    : box1, box -> box.a == NONE ? new ArrayList<>() : new ArrayList<>(Collections.singleton(box.a)));
1✔
905
        }
906
        if (n >= Integer.MAX_VALUE / 2)
1✔
907
            return collectingAndThen(Collectors.toList(), list -> {
1✔
908
                list.sort(comparator);
1✔
909
                if (list.size() <= n)
1✔
910
                    return list;
1✔
911
                return new ArrayList<>(list.subList(0, n));
×
912
            });
913
        return Collector.<T, Limiter<T>, List<T>>of(() -> new Limiter<>(n, comparator), Limiter::put, Limiter::putAll,
1✔
914
            pq -> {
915
                pq.sort();
1✔
916
                return new ArrayList<>(pq);
1✔
917
            });
918
    }
919

920
    /**
921
     * Returns a {@code Collector} which collects at most specified number of
922
     * the least stream elements according to the natural order into the
923
     * {@link List}. The resulting {@code List} is sorted in natural order
924
     * (least element is the first). The order of equal elements is the same as
925
     * in the input stream.
926
     * 
927
     * <p>
928
     * The operation performed by the returned collector is equivalent to
929
     * {@code stream.sorted().limit(n).collect(Collectors.toList())}, but
930
     * usually performed much faster if {@code n} is much less than the stream
931
     * size.
932
     * 
933
     * <p>
934
     * There are no guarantees on the type, mutability, serializability, or
935
     * thread-safety of the {@code List} returned.
936
     * 
937
     * <p>
938
     * When supplied {@code n} is less or equal to zero, this method returns a
939
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
940
     * collector</a> which ignores the input and produces an empty list.
941
     * 
942
     * @param <T> the type of the input elements
943
     * @param n maximum number of stream elements to preserve
944
     * @return a collector which returns a {@code List} containing the least n
945
     *         stream elements or less if the stream was shorter.
946
     */
947
    public static <T extends Comparable<? super T>> Collector<T, ?, List<T>> least(int n) {
948
        return least(Comparator.naturalOrder(), n);
1✔
949
    }
950

951
    /**
952
     * Returns a {@code Collector} which finds the index of the minimal stream
953
     * element according to the specified {@link Comparator}. If there are
954
     * several minimal elements, the index of the first one is returned.
955
     *
956
     * @param <T> the type of the input elements
957
     * @param comparator a {@code Comparator} to compare the elements
958
     * @return a {@code Collector} which finds the index of the minimal element.
959
     * @throws NullPointerException if comparator is null.
960
     * @see #minIndex()
961
     * @since 0.3.5
962
     */
963
    public static <T extends @Nullable Object> Collector<T, ?, OptionalLong> minIndex(Comparator<? super T> comparator) {
964
        Objects.requireNonNull(comparator);
1✔
965
        class Container {
1✔
966
            T value;
967
            long count = 0;
1✔
968
            long index = -1;
1✔
969
        }
970

971
        return Collector.of(Container::new, (c, t) -> {
1✔
972
            if (c.index == -1 || comparator.compare(c.value, t) > 0) {
1✔
973
                c.value = t;
1✔
974
                c.index = c.count;
1✔
975
            }
976
            c.count++;
1✔
977
        }, (c1, c2) -> {
1✔
978
            if (c1.index == -1 || (c2.index != -1 && comparator.compare(c1.value, c2.value) > 0)) {
1✔
979
                c2.index += c1.count;
1✔
980
                c2.count += c1.count;
1✔
981
                return c2;
1✔
982
            }
983
            c1.count += c2.count;
1✔
984
            return c1;
1✔
985
        }, c -> c.index == -1 ? OptionalLong.empty() : OptionalLong.of(c.index));
1✔
986
    }
987

988
    /**
989
     * Returns a {@code Collector} which finds the index of the minimal stream
990
     * element according to the elements natural order. If there are several
991
     * minimal elements, the index of the first one is returned.
992
     *
993
     * @param <T> the type of the input elements
994
     * @return a {@code Collector} which finds the index of the minimal element.
995
     * @see #minIndex(Comparator)
996
     * @since 0.3.5
997
     */
998
    public static <T extends Comparable<? super T>> Collector<T, ?, OptionalLong> minIndex() {
999
        return minIndex(Comparator.naturalOrder());
1✔
1000
    }
1001

1002
    /**
1003
     * Returns a {@code Collector} which finds the index of the maximal stream
1004
     * element according to the specified {@link Comparator}. If there are
1005
     * several maximal elements, the index of the first one is returned.
1006
     *
1007
     * @param <T> the type of the input elements
1008
     * @param comparator a {@code Comparator} to compare the elements
1009
     * @return a {@code Collector} which finds the index of the maximal element.
1010
     * @throws NullPointerException if comparator is null.
1011
     * @see #maxIndex()
1012
     * @since 0.3.5
1013
     */
1014
    public static <T extends @Nullable Object> Collector<T, ?, OptionalLong> maxIndex(Comparator<? super T> comparator) {
1015
        return minIndex(comparator.reversed());
1✔
1016
    }
1017

1018
    /**
1019
     * Returns a {@code Collector} which finds the index of the maximal stream
1020
     * element according to the elements natural order. If there are several
1021
     * maximal elements, the index of the first one is returned.
1022
     *
1023
     * @param <T> the type of the input elements
1024
     * @return a {@code Collector} which finds the index of the maximal element.
1025
     * @see #maxIndex(Comparator)
1026
     * @since 0.3.5
1027
     */
1028
    public static <T extends Comparable<? super T>> Collector<T, ?, OptionalLong> maxIndex() {
1029
        return minIndex(Comparator.reverseOrder());
1✔
1030
    }
1031

1032
    /**
1033
     * Returns a {@code Collector} implementing a cascaded "group by" operation
1034
     * on input elements of type {@code T}, for classification function which
1035
     * maps input elements to the enum values. The downstream reduction for
1036
     * repeating keys is performed using the specified downstream
1037
     * {@code Collector}.
1038
     *
1039
     * <p>
1040
     * Unlike the {@link Collectors#groupingBy(Function, Collector)} collector
1041
     * this collector produces an {@link EnumMap} which contains all possible
1042
     * keys including keys which were never returned by the classification
1043
     * function. These keys are mapped to the default collector value which is
1044
     * equivalent to collecting an empty stream with the same collector.
1045
     * 
1046
     * <p>
1047
     * This method returns a
1048
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1049
     * collector</a> if the downstream collector is short-circuiting. The
1050
     * collection might stop when for every possible enum key the downstream
1051
     * collection is known to be finished.
1052
     *
1053
     * @param <T> the type of the input elements
1054
     * @param <K> the type of the enum values returned by the classifier
1055
     * @param <A> the intermediate accumulation type of the downstream collector
1056
     * @param <D> the result type of the downstream reduction
1057
     * @param enumClass the class of enum values returned by the classifier
1058
     * @param classifier a classifier function mapping input elements to enum
1059
     *        values
1060
     * @param downstream a {@code Collector} implementing the downstream
1061
     *        reduction
1062
     * @return a {@code Collector} implementing the cascaded group-by operation
1063
     * @throws NullPointerException if enumClass is null, classifier is null, or downstream is null.
1064
     * @see Collectors#groupingBy(Function, Collector)
1065
     * @see #groupingBy(Function, Set, Supplier, Collector)
1066
     * @since 0.3.7
1067
     */
1068
    public static <
1069
            T extends @Nullable Object,
1070
            K extends Enum<K>,
1071
            A extends @Nullable Object,
1072
            D extends @Nullable Object> Collector<T, ?, EnumMap<K, D>> groupingByEnum(
1073
            Class<K> enumClass,
1074
            Function<? super T, K> classifier,
1075
            Collector<? super T, A, D> downstream) {
1076
        return groupingBy(classifier, EnumSet.allOf(enumClass), () -> new EnumMap<>(enumClass), downstream);
1✔
1077
    }
1078

1079
    /**
1080
     * Returns a {@code Collector} implementing a cascaded "group by" operation
1081
     * on input elements of type {@code T}, grouping elements according to a
1082
     * classification function, and then performing a reduction operation on the
1083
     * values associated with a given key using the specified downstream
1084
     * {@code Collector}.
1085
     *
1086
     * <p>
1087
     * There are no guarantees on the type, mutability, serializability, or
1088
     * thread-safety of the {@code Map} returned.
1089
     *
1090
     * <p>
1091
     * The main difference of this collector from
1092
     * {@link Collectors#groupingBy(Function, Collector)} is that it accepts
1093
     * additional domain parameter which is the {@code Set} of all possible map
1094
     * keys. If the mapper function produces the key out of domain, an
1095
     * {@code IllegalStateException} will occur. If the mapper function does not
1096
     * produce some of domain keys at all, they are also added to the result.
1097
     * These keys are mapped to the default collector value which is equivalent
1098
     * to collecting an empty stream with the same collector.
1099
     * 
1100
     * <p>
1101
     * This method returns a
1102
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1103
     * collector</a> if the downstream collector is short-circuiting. The
1104
     * collection might stop when for every possible key from the domain the
1105
     * downstream collection is known to be finished.
1106
     *
1107
     * @param <T> the type of the input elements
1108
     * @param <K> the type of the keys
1109
     * @param <A> the intermediate accumulation type of the downstream collector
1110
     * @param <D> the result type of the downstream reduction
1111
     * @param classifier a classifier function mapping input elements to keys
1112
     * @param domain a domain of all possible key values
1113
     * @param downstream a {@code Collector} implementing the downstream
1114
     *        reduction
1115
     * @return a {@code Collector} implementing the cascaded group-by operation
1116
     *         with given domain
1117
     * @throws NullPointerException if classifier is null, domain is null, or downstream is null.
1118
     *
1119
     * @see #groupingBy(Function, Set, Supplier, Collector)
1120
     * @see #groupingByEnum(Class, Function, Collector)
1121
     * @since 0.4.0
1122
     */
1123
    public static <
1124
            T extends @Nullable Object,
1125
            K,
1126
            D extends @Nullable Object,
1127
            A extends @Nullable Object> Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,
1128
            Set<K> domain, Collector<? super T, A, D> downstream) {
1129
        return groupingBy(classifier, domain, HashMap::new, downstream);
1✔
1130
    }
1131

1132
    /**
1133
     * Returns a {@code Collector} implementing a cascaded "group by" operation
1134
     * on input elements of type {@code T}, grouping elements according to a
1135
     * classification function, and then performing a reduction operation on the
1136
     * values associated with a given key using the specified downstream
1137
     * {@code Collector}. The {@code Map} produced by the Collector is created
1138
     * with the supplied factory function.
1139
     *
1140
     * <p>
1141
     * The main difference of this collector from
1142
     * {@link Collectors#groupingBy(Function, Supplier, Collector)} is that it
1143
     * accepts additional domain parameter which is the {@code Set} of all
1144
     * possible map keys. If the mapper function produces the key out of domain,
1145
     * an {@code IllegalStateException} will occur. If the mapper function does
1146
     * not produce some of domain keys at all, they are also added to the
1147
     * result. These keys are mapped to the default collector value which is
1148
     * equivalent to collecting an empty stream with the same collector.
1149
     * 
1150
     * <p>
1151
     * This method returns a
1152
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1153
     * collector</a> if the downstream collector is short-circuiting. The
1154
     * collection might stop when for every possible key from the domain the
1155
     * downstream collection is known to be finished.
1156
     *
1157
     * @param <T> the type of the input elements
1158
     * @param <K> the type of the keys
1159
     * @param <A> the intermediate accumulation type of the downstream collector
1160
     * @param <D> the result type of the downstream reduction
1161
     * @param <M> the type of the resulting {@code Map}
1162
     * @param classifier a classifier function mapping input elements to keys
1163
     * @param domain a domain of all possible key values
1164
     * @param downstream a {@code Collector} implementing the downstream
1165
     *        reduction
1166
     * @param mapFactory a function which, when called, produces a new empty
1167
     *        {@code Map} of the desired type
1168
     * @return a {@code Collector} implementing the cascaded group-by operation
1169
     *         with given domain
1170
     * @throws NullPointerException if classifier is null, domain is null, mapFactory is null, or downstream is null.
1171
     *
1172
     * @see #groupingBy(Function, Set, Collector)
1173
     * @see #groupingByEnum(Class, Function, Collector)
1174
     * @since 0.4.0
1175
     */
1176
    public static <
1177
            T extends @Nullable Object,
1178
            K,
1179
            D extends @Nullable Object,
1180
            A extends @Nullable Object,
1181
            M extends Map<K, D>> Collector<T, ?, M> groupingBy(
1182
            Function<? super T, ? extends K> classifier,
1183
            Set<K> domain,
1184
            Supplier<M> mapFactory,
1185
            Collector<? super T, A, D> downstream) {
1186
        Objects.requireNonNull(classifier);
1✔
1187
        Objects.requireNonNull(domain);
1✔
1188
        Objects.requireNonNull(mapFactory);
1✔
1189
        Supplier<A> downstreamSupplier = downstream.supplier();
1✔
1190
        Collector<T, ?, M> groupingBy;
1191
        Function<K, A> supplier = k -> {
1✔
1192
            if (!domain.contains(k))
1✔
1193
                throw new IllegalStateException("Classifier returned value '" + k + "' which is out of domain");
1✔
1194
            return downstreamSupplier.get();
1✔
1195
        };
1196
        BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
1✔
1197
        BiConsumer<Map<K, A>, T> accumulator = (m, t) -> {
1✔
1198
            K key = Objects.requireNonNull(classifier.apply(t));
1✔
1199
            A container = m.computeIfAbsent(key, supplier);
1✔
1200
            downstreamAccumulator.accept(container, t);
1✔
1201
        };
1✔
1202
        PartialCollector<Map<K, A>, M> partial = PartialCollector.grouping(mapFactory, downstream);
1✔
1203
        Predicate<A> downstreamFinished = finished(downstream);
1✔
1204
        if (downstreamFinished != null) {
1✔
1205
            int size = domain.size();
1✔
1206
            groupingBy = partial.asCancellable(accumulator, map -> {
1✔
1207
                if (map.size() < size)
1✔
1208
                    return false;
1✔
1209
                for (A container : map.values()) {
1✔
1210
                    if (!downstreamFinished.test(container))
1✔
1211
                        return false;
1✔
1212
                }
1✔
1213
                return true;
1✔
1214
            });
1215
        } else {
1✔
1216
            groupingBy = partial.asRef(accumulator);
1✔
1217
        }
1218
        return collectingAndThen(groupingBy, map -> {
1✔
1219
            Function<A, D> finisher = downstream.finisher();
1✔
1220
            domain.forEach(key -> map.computeIfAbsent(key, k -> finisher.apply(downstreamSupplier.get())));
1✔
1221
            return map;
1✔
1222
        });
1223
    }
1224

1225
    /**
1226
     * Returns a {@code Collector} which collects the intersection of the input
1227
     * collections into the newly-created {@link Set}.
1228
     *
1229
     * <p>
1230
     * The returned collector produces an empty set if the input is empty or
1231
     * intersection of the input collections is empty.
1232
     * 
1233
     * <p>
1234
     * There are no guarantees on the type, mutability, serializability, or
1235
     * thread-safety of the {@code Set} returned.
1236
     *
1237
     * <p>
1238
     * This method returns a
1239
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1240
     * collector</a>: it may not process all the elements if the resulting
1241
     * intersection is empty.
1242
     * 
1243
     * @param <T> the type of the elements in the input collections
1244
     * @param <S> the type of the input collections
1245
     * @return a {@code Collector} which finds all the minimal elements and
1246
     *         collects them to the {@code List}.
1247
     * @since 0.4.0
1248
     */
1249
    public static <T extends @Nullable Object, S extends Collection<T>> Collector<S, ?, Set<T>> intersecting() {
1250
        return new CancellableCollectorImpl<S, Box<Set<T>>, Set<T>>(Box::new, (b, t) -> {
1✔
1251
            if (b.a == null) {
1✔
1252
                b.a = new HashSet<>(t);
1✔
1253
            } else {
1254
                b.a.retainAll(t);
1✔
1255
            }
1256
        }, (b1, b2) -> {
1✔
1257
            if (b1.a == null)
1✔
1258
                return b2;
1✔
1259
            if (b2.a != null)
1✔
1260
                b1.a.retainAll(b2.a);
1✔
1261
            return b1;
1✔
1262
        }, b -> b.a == null ? Collections.emptySet() : b.a, b -> b.a != null && b.a.isEmpty(),
1✔
1263
                UNORDERED_CHARACTERISTICS);
1264
    }
1265

1266
    /**
1267
     * Adapts a {@code Collector} to perform an additional finishing
1268
     * transformation.
1269
     * 
1270
     * <p>
1271
     * Unlike {@link Collectors#collectingAndThen(Collector, Function)} this
1272
     * method returns a
1273
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1274
     * collector</a> if the downstream collector is short-circuiting.
1275
     *
1276
     * @param <T> the type of the input elements
1277
     * @param <A> intermediate accumulation type of the downstream collector
1278
     * @param <R> result type of the downstream collector
1279
     * @param <RR> result type of the resulting collector
1280
     * @param downstream a collector
1281
     * @param finisher a function to be applied to the final result of the
1282
     *        downstream collector
1283
     * @return a collector which performs the action of the downstream
1284
     *         collector, followed by an additional finishing step
1285
     * @throws NullPointerException if downstream is null, or finisher is null.
1286
     * @see Collectors#collectingAndThen(Collector, Function)
1287
     * @since 0.4.0
1288
     */
1289
    public static <
1290
            T extends @Nullable Object,
1291
            A extends @Nullable Object,
1292
            R extends @Nullable Object,
1293
            RR extends @Nullable Object> Collector<T, A, RR> collectingAndThen(Collector<T, A, R> downstream,
1294
            Function<R, RR> finisher) {
1295
        Predicate<A> finished = finished(downstream);
1✔
1296
        if (finished != null) {
1✔
1297
            return new CancellableCollectorImpl<>(downstream.supplier(), downstream.accumulator(), downstream
1✔
1298
                    .combiner(), downstream.finisher().andThen(finisher), finished, downstream.characteristics()
1✔
1299
                            .contains(Characteristics.UNORDERED) ? UNORDERED_CHARACTERISTICS : NO_CHARACTERISTICS);
1✔
1300
        }
1301
        return Collectors.collectingAndThen(downstream, finisher);
1✔
1302
    }
1303

1304
    /**
1305
     * Returns a {@code Collector} which partitions the input elements according
1306
     * to a {@code Predicate}, reduces the values in each partition according to
1307
     * another {@code Collector}, and organizes them into a
1308
     * {@code Map<Boolean, D>} whose values are the result of the downstream
1309
     * reduction.
1310
     * 
1311
     * <p>
1312
     * Unlike {@link Collectors#partitioningBy(Predicate, Collector)} this
1313
     * method returns a
1314
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1315
     * collector</a> if the downstream collector is short-circuiting.
1316
     * 
1317
     * @param <T> the type of the input elements
1318
     * @param <A> the intermediate accumulation type of the downstream collector
1319
     * @param <D> the result type of the downstream reduction
1320
     * @param predicate a predicate used for classifying input elements
1321
     * @param downstream a {@code Collector} implementing the downstream
1322
     *        reduction
1323
     * @return a {@code Collector} implementing the cascaded partitioning
1324
     *         operation
1325
     * @throws NullPointerException if predicate is null, or downstream is null.
1326
     * @since 0.4.0
1327
     * @see Collectors#partitioningBy(Predicate, Collector)
1328
     */
1329
    public static <
1330
            T extends @Nullable Object,
1331
            D extends @Nullable Object,
1332
            A extends @Nullable Object> Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate,
1333
            Collector<? super T, A, D> downstream) {
1334
        Objects.requireNonNull(predicate);
1✔
1335
        Predicate<A> finished = finished(downstream);
1✔
1336
        if (finished != null) {
1✔
1337
            BiConsumer<A, ? super T> accumulator = downstream.accumulator();
1✔
1338
            return BooleanMap.partialCollector(downstream).asCancellable((map, t) -> accumulator.accept(predicate.test(
1✔
1339
                t) ? map.trueValue : map.falseValue, t), map -> finished.test(map.trueValue) && finished.test(
1✔
1340
                    map.falseValue));
1341
        }
1342
        return Collectors.partitioningBy(predicate, downstream);
1✔
1343
    }
1344

1345
    /**
1346
     * Adapts a {@code Collector} accepting elements of type {@code U} to one
1347
     * accepting elements of type {@code T} by applying a mapping function to
1348
     * each input element before accumulation.
1349
     *
1350
     * <p>
1351
     * Unlike {@link Collectors#mapping(Function, Collector)} this method
1352
     * returns a
1353
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1354
     * collector</a> if the downstream collector is short-circuiting.
1355
     * 
1356
     * @param <T> the type of the input elements
1357
     * @param <U> type of elements accepted by downstream collector
1358
     * @param <A> intermediate accumulation type of the downstream collector
1359
     * @param <R> result type of collector
1360
     * @param mapper a function to be applied to the input elements
1361
     * @param downstream a collector which will accept mapped values
1362
     * @return a collector which applies the mapping function to the input
1363
     *         elements and provides the mapped results to the downstream
1364
     *         collector
1365
     * @throws NullPointerException if mapper is null, or downstream is null.
1366
     * @see Collectors#mapping(Function, Collector)
1367
     * @since 0.4.0
1368
     */
1369
    public static <
1370
            T extends @Nullable Object,
1371
            U extends @Nullable Object,
1372
            A extends @Nullable Object,
1373
            R extends @Nullable Object> Collector<T, ?, R> mapping(Function<? super T, ? extends U> mapper,
1374
            Collector<? super U, A, R> downstream) {
1375
        Objects.requireNonNull(mapper);
1✔
1376
        Predicate<A> finished = finished(downstream);
1✔
1377
        if (finished != null) {
1✔
1378
            BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator();
1✔
1379
            return new CancellableCollectorImpl<>(downstream.supplier(), (acc, t) -> {
1✔
1380
                if (!finished.test(acc))
1✔
1381
                    downstreamAccumulator.accept(acc, mapper.apply(t));
1✔
1382
            }, downstream.combiner(), downstream.finisher(), finished, downstream.characteristics());
1✔
1383
        }
1384
        return Collectors.mapping(mapper, downstream);
1✔
1385
    }
1386

1387
    /**
1388
     * Returns a collector which collects input elements to the new {@code List}
1389
     * transforming them with the supplied function beforehand.
1390
     * 
1391
     * <p>
1392
     * This method behaves like
1393
     * {@code Collectors.mapping(mapper, Collectors.toList())}.
1394
     * 
1395
     * <p>
1396
     * There are no guarantees on the type, mutability, serializability, or
1397
     * thread-safety of the {@code List} returned.
1398
     * 
1399
     * @param <T> the type of the input elements
1400
     * @param <U> the resulting type of the mapper function
1401
     * @param mapper a function to be applied to the input elements
1402
     * @return a collector which applies the mapping function to the input
1403
     *         elements and collects the mapped results to the {@code List}
1404
     * @throws NullPointerException if mapper is null.
1405
     * @see #mapping(Function, Collector)
1406
     * @since 0.6.0
1407
     */
1408
    public static <
1409
            T extends @Nullable Object,
1410
            U extends @Nullable Object> Collector<T, ?, List<U>> mapping(Function<? super T, ? extends U> mapper) {
1411
        return Collectors.mapping(mapper, Collectors.toList());
1✔
1412
    }
1413

1414
    /**
1415
     * Adapts a {@code Collector} accepting elements of type {@code U} to one
1416
     * accepting elements of type {@code T} by applying a flat mapping function
1417
     * to each input element before accumulation. The flat mapping function maps
1418
     * an input element to a {@link Stream stream} covering zero or more output
1419
     * elements that are then accumulated downstream. Each mapped stream is
1420
     * {@link java.util.stream.BaseStream#close() closed} after its contents
1421
     * have been placed downstream. (If a mapped stream is {@code null} an empty
1422
     * stream is used, instead.)
1423
     * 
1424
     * <p>
1425
     * This method is similar to {@code Collectors.flatMapping} method which
1426
     * appears in JDK 9. However when downstream collector is
1427
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting</a>
1428
     * , this method will also return a short-circuiting collector.
1429
     * 
1430
     * @param <T> the type of the input elements
1431
     * @param <U> type of elements accepted by downstream collector
1432
     * @param <A> intermediate accumulation type of the downstream collector
1433
     * @param <R> result type of collector
1434
     * @param mapper a function to be applied to the input elements, which
1435
     *        returns a stream of results
1436
     * @param downstream a collector which will receive the elements of the
1437
     *        stream returned by mapper
1438
     * @return a collector which applies the mapping function to the input
1439
     *         elements and provides the flat mapped results to the downstream
1440
     *         collector
1441
     * @throws NullPointerException if mapper is null, or downstream is null.
1442
     * @since 0.4.1
1443
     */
1444
    public static <
1445
            T extends @Nullable Object,
1446
            U extends @Nullable Object,
1447
            A extends @Nullable Object,
1448
            R extends @Nullable Object> Collector<T, ?, R> flatMapping(
1449
            Function<? super T, ? extends @Nullable Stream<? extends U>> mapper,
1450
            Collector<? super U, A, R> downstream) {
1451
        Objects.requireNonNull(mapper);
1✔
1452
        BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator();
1✔
1453
        Predicate<A> finished = finished(downstream);
1✔
1454
        if (finished != null) {
1✔
1455
            return new CancellableCollectorImpl<>(downstream.supplier(), (acc, t) -> {
1✔
1456
                if (finished.test(acc))
1✔
1457
                    return;
1✔
1458
                try (Stream<? extends U> stream = mapper.apply(t)) {
1✔
1459
                    if (stream != null) {
1✔
1460
                        stream.spliterator().forEachRemaining(u -> {
1✔
1461
                            downstreamAccumulator.accept(acc, u);
1✔
1462
                            if (finished.test(acc))
1✔
1463
                                throw new CancelException();
1✔
1464
                        });
1✔
1465
                    }
1466
                } catch (CancelException ex) {
1✔
1467
                    // ignore
1468
                }
1✔
1469
            }, downstream.combiner(), downstream.finisher(), finished, downstream.characteristics());
1✔
1470
        }
1471
        return Collector.of(downstream.supplier(), (acc, t) -> {
1✔
1472
            try (Stream<? extends U> stream = mapper.apply(t)) {
1✔
1473
                if (stream != null) {
1✔
1474
                    stream.spliterator().forEachRemaining(u -> downstreamAccumulator.accept(acc, u));
1✔
1475
                }
1476
            }
1477
        }, downstream.combiner(), downstream.finisher(), downstream.characteristics().toArray(new Characteristics[0]));
1✔
1478
    }
1479

1480
    /**
1481
     * Returns a collector which launches a flat mapping function for each input
1482
     * element and collects the elements of the resulting streams to the flat
1483
     * {@code List}. Each mapped stream is
1484
     * {@link java.util.stream.BaseStream#close() closed} after its contents
1485
     * have been placed downstream. (If a mapped stream is {@code null} an empty
1486
     * stream is used, instead.)
1487
     * 
1488
     * <p>
1489
     * This method behaves like {@code flatMapping(mapper, Collectors.toList())}
1490
     * .
1491
     * 
1492
     * <p>
1493
     * There are no guarantees on the type, mutability, serializability, or
1494
     * thread-safety of the {@code List} returned.
1495
     * 
1496
     * @param <T> the type of the input elements
1497
     * @param <U> type of the resulting elements
1498
     * @param mapper a function to be applied to the input elements, which
1499
     *        returns a stream of results
1500
     * @return a collector which applies the mapping function to the input
1501
     *         elements and collects the flat mapped results to the {@code List}
1502
     * @throws NullPointerException if mapper is null.
1503
     * @since 0.6.0
1504
     */
1505
    public static <T extends @Nullable Object, U extends @Nullable Object> Collector<T, ?, List<U>> flatMapping(
1506
            Function<? super T, ? extends @Nullable Stream<? extends U>> mapper) {
1507
        return flatMapping(mapper, Collectors.toList());
1✔
1508
    }
1509

1510
    /**
1511
     * Returns a {@code Collector} which passes only those elements to the
1512
     * specified downstream collector which match given predicate.
1513
     *
1514
     * <p>
1515
     * This method returns a
1516
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1517
     * collector</a> if downstream collector is short-circuiting.
1518
     * 
1519
     * <p>
1520
     * The operation performed by the returned collector is equivalent to
1521
     * {@code stream.filter(predicate).collect(downstream)}. This collector is
1522
     * mostly useful as a downstream collector in cascaded operation involving
1523
     * {@link #pairing(Collector, Collector, BiFunction)} collector.
1524
     *
1525
     * <p>
1526
     * This method is similar to {@code Collectors.filtering} method which
1527
     * appears in JDK 9. However when downstream collector is
1528
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting</a>
1529
     * , this method will also return a short-circuiting collector.
1530
     * 
1531
     * @param <T> the type of the input elements
1532
     * @param <A> intermediate accumulation type of the downstream collector
1533
     * @param <R> result type of collector
1534
     * @param predicate a filter function to be applied to the input elements
1535
     * @param downstream a collector which will accept filtered values
1536
     * @return a collector which applies the predicate to the input elements and
1537
     *         provides the elements for which predicate returned true to the
1538
     *         downstream collector
1539
     * @throws NullPointerException if predicate is null, or downstream is null.
1540
     * @see #pairing(Collector, Collector, BiFunction)
1541
     * @since 0.4.0
1542
     */
1543
    public static <
1544
            T extends @Nullable Object, 
1545
            A extends @Nullable Object, 
1546
            R extends @Nullable Object> Collector<T, ?, R> filtering(Predicate<? super T> predicate,
1547
            Collector<T, A, R> downstream) {
1548
        Objects.requireNonNull(predicate);
1✔
1549
        BiConsumer<A, T> downstreamAccumulator = downstream.accumulator();
1✔
1550
        BiConsumer<A, T> accumulator = (acc, t) -> {
1✔
1551
            if (predicate.test(t))
1✔
1552
                downstreamAccumulator.accept(acc, t);
1✔
1553
        };
1✔
1554
        Predicate<A> finished = finished(downstream);
1✔
1555
        if (finished != null) {
1✔
1556
            return new CancellableCollectorImpl<>(downstream.supplier(), accumulator, downstream.combiner(), downstream
1✔
1557
                    .finisher(), finished, downstream.characteristics());
1✔
1558
        }
1559
        return Collector.of(downstream.supplier(), accumulator, downstream.combiner(), downstream.finisher(), downstream
1✔
1560
                .characteristics().toArray(new Characteristics[0]));
1✔
1561
    }
1562

1563
    /**
1564
     * Returns a {@code Collector} which filters input elements by the supplied
1565
     * predicate, collecting them to the list.
1566
     *
1567
     * <p>
1568
     * This method behaves like
1569
     * {@code filtering(predicate, Collectors.toList())}.
1570
     * 
1571
     * <p>
1572
     * There are no guarantees on the type, mutability, serializability, or
1573
     * thread-safety of the {@code List} returned.
1574
     * 
1575
     * @param <T> the type of the input elements
1576
     * @param predicate a filter function to be applied to the input elements
1577
     * @return a collector which applies the predicate to the input elements and
1578
     *         collects the elements for which predicate returned true to the
1579
     *         {@code List}
1580
     * @throws NullPointerException if predicate is null.
1581
     * @see #filtering(Predicate, Collector)
1582
     * @since 0.6.0
1583
     */
1584
    public static <T extends @Nullable Object> Collector<T, ?, List<T>> filtering(Predicate<? super T> predicate) {
1585
        return filtering(predicate, Collectors.toList());
1✔
1586
    }
1587

1588
    /**
1589
     * Returns a {@code Collector} which performs the bitwise-and operation of a
1590
     * integer-valued function applied to the input elements. If no elements are
1591
     * present, the result is empty {@link OptionalInt}.
1592
     *
1593
     * <p>
1594
     * This method returns a
1595
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1596
     * collector</a>: it may not process all the elements if the result is zero.
1597
     * 
1598
     * @param <T> the type of the input elements
1599
     * @param mapper a function extracting the property to be processed
1600
     * @return a {@code Collector} that produces the bitwise-and operation of a
1601
     *         derived property
1602
     * @throws NullPointerException if mapper is null.
1603
     * @since 0.4.0
1604
     */
1605
    public static <T extends @Nullable Object> Collector<T, ?, OptionalInt> andingInt(ToIntFunction<T> mapper) {
1606
        Objects.requireNonNull(mapper);
1✔
1607
        return new CancellableCollectorImpl<>(PrimitiveBox::new, (acc, t) -> {
1✔
1608
            if (!acc.b) {
1✔
1609
                acc.i = mapper.applyAsInt(t);
1✔
1610
                acc.b = true;
1✔
1611
            } else {
1612
                acc.i &= mapper.applyAsInt(t);
1✔
1613
            }
1614
        }, (acc1, acc2) -> {
1✔
1615
            if (!acc1.b)
1✔
1616
                return acc2;
1✔
1617
            if (!acc2.b)
1✔
1618
                return acc1;
1✔
1619
            acc1.i &= acc2.i;
1✔
1620
            return acc1;
1✔
1621
        }, PrimitiveBox::asInt, acc -> acc.b && acc.i == 0, UNORDERED_CHARACTERISTICS);
1✔
1622
    }
1623

1624
    /**
1625
     * Returns a {@code Collector} which performs the bitwise-and operation of a
1626
     * long-valued function applied to the input elements. If no elements are
1627
     * present, the result is empty {@link OptionalLong}.
1628
     *
1629
     * <p>
1630
     * This method returns a
1631
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1632
     * collector</a>: it may not process all the elements if the result is zero.
1633
     * 
1634
     * @param <T> the type of the input elements
1635
     * @param mapper a function extracting the property to be processed
1636
     * @return a {@code Collector} that produces the bitwise-and operation of a
1637
     *         derived property
1638
     * @throws NullPointerException if mapper is null.
1639
     * @since 0.4.0
1640
     */
1641
    public static <T extends @Nullable Object> Collector<T, ?, OptionalLong> andingLong(ToLongFunction<T> mapper) {
1642
        Objects.requireNonNull(mapper);
1✔
1643
        return new CancellableCollectorImpl<>(PrimitiveBox::new, (acc, t) -> {
1✔
1644
            if (!acc.b) {
1✔
1645
                acc.l = mapper.applyAsLong(t);
1✔
1646
                acc.b = true;
1✔
1647
            } else {
1648
                acc.l &= mapper.applyAsLong(t);
1✔
1649
            }
1650
        }, (acc1, acc2) -> {
1✔
1651
            if (!acc1.b)
1✔
1652
                return acc2;
1✔
1653
            if (!acc2.b)
1✔
1654
                return acc1;
1✔
1655
            acc1.l &= acc2.l;
1✔
1656
            return acc1;
1✔
1657
        }, PrimitiveBox::asLong, acc -> acc.b && acc.l == 0, UNORDERED_CHARACTERISTICS);
1✔
1658
    }
1659

1660
    /**
1661
     * Returns a {@code Collector} which computes a common prefix of input
1662
     * {@code CharSequence} objects returning the result as {@code String}. For
1663
     * empty input the empty {@code String} is returned.
1664
     *
1665
     * <p>
1666
     * The returned {@code Collector} handles specially Unicode surrogate pairs:
1667
     * the returned prefix may end with
1668
     * <a href="http://www.unicode.org/glossary/#high_surrogate_code_unit">
1669
     * Unicode high-surrogate code unit</a> only if it's not succeeded by
1670
     * <a href="http://www.unicode.org/glossary/#low_surrogate_code_unit">
1671
     * Unicode low-surrogate code unit</a> in any of the input sequences.
1672
     * Normally the ending high-surrogate code unit is removed from the prefix.
1673
     * 
1674
     * <p>
1675
     * This method returns a
1676
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1677
     * collector</a>: it may not process all the elements if the common prefix
1678
     * is empty.
1679
     * 
1680
     * @return a {@code Collector} which computes a common prefix.
1681
     * @since 0.5.0
1682
     */
1683
    public static Collector<CharSequence, ?, String> commonPrefix() {
1684
        BiConsumer<ObjIntBox<CharSequence>, CharSequence> accumulator = (acc, t) -> {
1✔
1685
            if (acc.b == -1) {
1✔
1686
                acc.a = t;
1✔
1687
                acc.b = t.length();
1✔
1688
            } else if (acc.b > 0) {
1✔
1689
                if (t.length() < acc.b)
1✔
1690
                    acc.b = t.length();
1✔
1691
                for (int i = 0; i < acc.b; i++) {
1✔
1692
                    if (acc.a.charAt(i) != t.charAt(i)) {
1✔
1693
                        if (i > 0 && Character.isHighSurrogate(t.charAt(i - 1)) && (Character.isLowSurrogate(t.charAt(
1✔
1694
                            i)) || Character.isLowSurrogate(acc.a.charAt(i))))
1✔
1695
                            i--;
1✔
1696
                        acc.b = i;
1✔
1697
                        break;
1✔
1698
                    }
1699
                }
1700
            }
1701
        };
1✔
1702
        return new CancellableCollectorImpl<>(() -> new ObjIntBox<>(null, -1), accumulator, (acc1, acc2) -> {
1✔
1703
            if (acc1.b == -1)
1✔
1704
                return acc2;
1✔
1705
            if (acc2.b != -1)
1✔
1706
                accumulator.accept(acc1, acc2.a.subSequence(0, acc2.b));
1✔
1707
            return acc1;
1✔
1708
        }, acc -> acc.a == null ? "" : acc.a.subSequence(0, acc.b).toString(), acc -> acc.b == 0,
1✔
1709
                UNORDERED_CHARACTERISTICS);
1710
    }
1711

1712
    /**
1713
     * Returns a {@code Collector} which computes a common suffix of input
1714
     * {@code CharSequence} objects returning the result as {@code String}. For
1715
     * empty input the empty {@code String} is returned.
1716
     *
1717
     * <p>
1718
     * The returned {@code Collector} handles specially Unicode surrogate pairs:
1719
     * the returned suffix may start with
1720
     * <a href="http://www.unicode.org/glossary/#low_surrogate_code_unit">
1721
     * Unicode low-surrogate code unit</a> only if it's not preceded by
1722
     * <a href="http://www.unicode.org/glossary/#high_surrogate_code_unit">
1723
     * Unicode high-surrogate code unit</a> in any of the input sequences.
1724
     * Normally the starting low-surrogate code unit is removed from the suffix.
1725
     * 
1726
     * <p>
1727
     * This method returns a
1728
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1729
     * collector</a>: it may not process all the elements if the common suffix
1730
     * is empty.
1731
     * 
1732
     * @return a {@code Collector} which computes a common suffix.
1733
     * @since 0.5.0
1734
     */
1735
    public static Collector<CharSequence, ?, String> commonSuffix() {
1736
        BiConsumer<ObjIntBox<CharSequence>, CharSequence> accumulator = (acc, t) -> {
1✔
1737
            if (acc.b == -1) {
1✔
1738
                acc.a = t;
1✔
1739
                acc.b = t.length();
1✔
1740
            } else if (acc.b > 0) {
1✔
1741
                int aLen = acc.a.length();
1✔
1742
                int bLen = t.length();
1✔
1743
                if (bLen < acc.b)
1✔
1744
                    acc.b = bLen;
1✔
1745
                for (int i = 0; i < acc.b; i++) {
1✔
1746
                    if (acc.a.charAt(aLen - 1 - i) != t.charAt(bLen - 1 - i)) {
1✔
1747
                        if (i > 0 && Character.isLowSurrogate(t.charAt(bLen - i)) && (Character.isHighSurrogate(t
1✔
1748
                                .charAt(bLen - 1 - i)) || Character.isHighSurrogate(acc.a.charAt(aLen - 1 - i))))
1✔
1749
                            i--;
1✔
1750
                        acc.b = i;
1✔
1751
                        break;
1✔
1752
                    }
1753
                }
1754
            }
1755
        };
1✔
1756
        return new CancellableCollectorImpl<>(() -> new ObjIntBox<>(null, -1), accumulator, (acc1, acc2) -> {
1✔
1757
            if (acc1.b == -1)
1✔
1758
                return acc2;
1✔
1759
            if (acc2.b != -1)
1✔
1760
                accumulator.accept(acc1, acc2.a.subSequence(acc2.a.length() - acc2.b, acc2.a.length()));
1✔
1761
            return acc1;
1✔
1762
        }, acc -> acc.a == null ? "" : acc.a.subSequence(acc.a.length() - acc.b, acc.a.length()).toString(),
1✔
1763
                acc -> acc.b == 0, UNORDERED_CHARACTERISTICS);
1✔
1764
    }
1765

1766
    /**
1767
     * Returns a collector which collects input elements into {@code List}
1768
     * removing the elements following their dominator element. The dominator
1769
     * elements are defined according to given isDominator {@code BiPredicate}.
1770
     * The isDominator relation must be transitive (if A dominates over B and B
1771
     * dominates over C, then A also dominates over C).
1772
     * 
1773
     * <p>
1774
     * This operation is similar to
1775
     * {@code streamEx.collapse(isDominator).toList()}. The important difference
1776
     * is that in this method {@code BiPredicate} accepts not the adjacent
1777
     * stream elements, but the leftmost element of the series (current
1778
     * dominator) and the current element.
1779
     * 
1780
     * <p>
1781
     * For example, consider the stream of numbers:
1782
     * 
1783
     * <pre>{@code
1784
     * StreamEx<Integer> stream = StreamEx.of(1, 5, 3, 4, 2, 7);
1785
     * }</pre>
1786
     * 
1787
     * <p>
1788
     * Using {@code stream.collapse((a, b) -> a >= b).toList()} you will get the
1789
     * numbers which are bigger than their immediate predecessor (
1790
     * {@code [1, 5, 4, 7]}), because (3, 4) pair is not collapsed. However
1791
     * using {@code stream.collect(dominators((a, b) -> a >= b))} you will get
1792
     * the numbers which are bigger than any predecessor ({@code [1, 5, 7]}) as
1793
     * 5 is the dominator element for the subsequent 3, 4 and 2.
1794
     * 
1795
     * @param <T> type of the input elements.
1796
     * @param isDominator a non-interfering, stateless, transitive
1797
     *        {@code BiPredicate} which returns true if the first argument is
1798
     *        the dominator for the second argument.
1799
     * @return a collector which collects input element into {@code List}
1800
     *         leaving only dominator elements.
1801
     * @throws NullPointerException if isDominator is null.
1802
     * @see StreamEx#collapse(BiPredicate)
1803
     * @since 0.5.1
1804
     */
1805
    public static <T extends @Nullable Object> Collector<T, ?, List<T>> dominators(
1806
            BiPredicate<? super T, ? super T> isDominator) {
1807
        Objects.requireNonNull(isDominator);
1✔
1808
        return Collector.of(ArrayList::new, (acc, t) -> {
1✔
1809
            if (acc.isEmpty() || !isDominator.test(acc.get(acc.size() - 1), t))
1✔
1810
                acc.add(t);
1✔
1811
        }, (acc1, acc2) -> {
1✔
1812
            if (acc1.isEmpty())
1✔
1813
                return acc2;
1✔
1814
            int i = 0, l = acc2.size();
1✔
1815
            T last = acc1.get(acc1.size() - 1);
1✔
1816
            while (i < l && isDominator.test(last, acc2.get(i)))
1✔
1817
                i++;
1✔
1818
            if (i < l)
1✔
1819
                acc1.addAll(acc2.subList(i, l));
1✔
1820
            return acc1;
1✔
1821
        });
1822
    }
1823

1824
    /**
1825
     * Returns a {@code Collector} which performs downstream reduction if all
1826
     * elements satisfy the {@code Predicate}. The result is described as an
1827
     * {@code Optional<R>}.
1828
     * 
1829
     * <p>
1830
     * The resulting collector returns an empty optional if at least one input
1831
     * element does not satisfy the predicate. Otherwise it returns an optional
1832
     * which contains the result of the downstream collector.
1833
     * 
1834
     * <p>
1835
     * This method returns a
1836
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1837
     * collector</a>: it may not process all the elements if some of items don't
1838
     * satisfy the predicate or if downstream collector is a short-circuiting
1839
     * collector.
1840
     * 
1841
     * <p>
1842
     * It's guaranteed that the downstream collector is not called for elements
1843
     * which don't satisfy the predicate.
1844
     *
1845
     * @param <T> the type of input elements
1846
     * @param <A> intermediate accumulation type of the downstream collector
1847
     * @param <R> result type of the downstream collector
1848
     * @param predicate a non-interfering, stateless predicate to checks whether
1849
     *        collector should proceed with element
1850
     * @param downstream a {@code Collector} implementing the downstream
1851
     *        reduction
1852
     * @return a {@code Collector} witch performs downstream reduction if all
1853
     *         elements satisfy the predicate
1854
     * @throws NullPointerException if mapper is null.
1855
     * @see Stream#allMatch(Predicate)
1856
     * @see AbstractStreamEx#dropWhile(Predicate)
1857
     * @see AbstractStreamEx#takeWhile(Predicate)
1858
     * @since 0.6.3
1859
     */
1860
    public static <
1861
            T extends @Nullable Object, 
1862
            A extends @Nullable Object, 
1863
            R> Collector<T, ?, Optional<R>> ifAllMatch(Predicate<T> predicate,
1864
            Collector<T, A, R> downstream) {
1865
        Objects.requireNonNull(predicate);
1✔
1866
        Predicate<A> finished = finished(downstream);
1✔
1867
        Supplier<A> supplier = downstream.supplier();
1✔
1868
        BiConsumer<A, T> accumulator = downstream.accumulator();
1✔
1869
        BinaryOperator<A> combiner = downstream.combiner();
1✔
1870
        return new CancellableCollectorImpl<>(
1✔
1871
                () -> new PairBox<>(supplier.get(), Boolean.TRUE),
1✔
1872
                (acc, t) -> {
1873
                    if (acc.b && predicate.test(t)) {
1✔
1874
                        accumulator.accept(acc.a, t);
1✔
1875
                    } else {
1876
                        acc.b = Boolean.FALSE;
1✔
1877
                    }
1878
                },
1✔
1879
                (acc1, acc2) -> {
1880
                    if (acc1.b && acc2.b) {
1✔
1881
                        acc1.a = combiner.apply(acc1.a, acc2.a);
1✔
1882
                    } else {
1883
                        acc1.b = Boolean.FALSE;
1✔
1884
                    }
1885
                    return acc1;
1✔
1886
                },
1887
                acc -> acc.b ? Optional.of(downstream.finisher().apply(acc.a)) : Optional.empty(),
1✔
1888
                finished == null ? acc -> !acc.b : acc -> !acc.b || finished.test(acc.a),
1✔
1889
                downstream.characteristics().contains(Characteristics.UNORDERED) ? UNORDERED_CHARACTERISTICS
1✔
1890
                        : NO_CHARACTERISTICS);
1✔
1891
    }
1892

1893
    /**
1894
     * Returns a {@code Collector} which performs a possibly short-circuiting reduction of its
1895
     * input elements under a specified {@code BinaryOperator}. The result
1896
     * is described as an {@code Optional<T>}.
1897
     *
1898
     * <p>
1899
     * This collector behaves like {@link Collectors#reducing(BinaryOperator)}. However,
1900
     * it additionally accepts a zero element (also known as absorbing element). When zero element
1901
     * is passed to the accumulator then the result must be zero as well. So the collector
1902
     * takes the advantage of this and may short-circuit if zero is reached during the collection.
1903
     *
1904
     * <p>
1905
     * This method returns a
1906
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1907
     * collector</a>: it may not process all the elements if the result of reduction is equal to zero.
1908
     *
1909
     * <p>
1910
     * This collector is mostly useful as a downstream collector. To perform simple
1911
     * short-circuiting reduction, use {@link AbstractStreamEx#reduceWithZero(Object, BinaryOperator)}
1912
     * instead.
1913
     *
1914
     * @param zero zero element
1915
     * @param op an <a href="package-summary.html#Associativity">associative</a>
1916
     *        , <a href="package-summary.html#NonInterference">non-interfering
1917
     *        </a>, <a href="package-summary.html#Statelessness">stateless</a>
1918
     *        function to combine two elements into one.
1919
     * @param <T> the type of input elements
1920
     * @return a collector which returns an {@link Optional} describing the reduction result.
1921
     *         For empty stream an empty {@code Optional} is returned.
1922
     * @throws NullPointerException if op is null or the result of reduction is null
1923
     * @see #reducingWithZero(Object, Object, BinaryOperator)
1924
     * @see AbstractStreamEx#reduceWithZero(Object, BinaryOperator)
1925
     * @see Collectors#reducing(BinaryOperator)
1926
     * @since 0.7.3
1927
     */
1928
    public static <T> Collector<T, ?, Optional<T>> reducingWithZero(T zero, BinaryOperator<T> op) {
1929
        Objects.requireNonNull(op);
1✔
1930
        // acc.b: 0 = no element, 1 = has element, 2 = zero reached
1931
        return new CancellableCollectorImpl<>(
1✔
1932
            () -> new ObjIntBox<T>(null, 0),
1✔
1933
            (acc, t) -> {
1934
                if (acc.b != 2) {
1✔
1935
                    if (acc.b == 1) {
1✔
1936
                        t = op.apply(t, acc.a);
1✔
1937
                    }
1938
                    if (Objects.equals(t, zero)) {
1✔
1939
                        acc.b = 2;
1✔
1940
                        acc.a = zero;
1✔
1941
                    } else {
1942
                        acc.b = 1;
1✔
1943
                        acc.a = t;
1✔
1944
                    }
1945
                }
1946
            },
1✔
1947
            (acc1, acc2) -> {
1948
                if (acc1.b == 0 || acc2.b == 2) return acc2;
1✔
1949
                if (acc2.b == 0 || acc1.b == 2) return acc1;
1✔
1950
                T t = op.apply(acc1.a, acc2.a);
1✔
1951
                if (Objects.equals(t, zero)) {
1✔
1952
                    acc1.b = 2;
1✔
1953
                    acc1.a = zero;
1✔
1954
                } else {
1955
                    acc1.a = t;
1✔
1956
                }
1957
                return acc1;
1✔
1958
            },
1959
            acc -> acc.b == 0 ? Optional.empty() : Optional.of(acc.a),
1✔
1960
            acc -> acc.b == 2,
1✔
1961
            UNORDERED_CHARACTERISTICS
1962
        );
1963
    }
1964

1965
    /**
1966
     * Returns a {@code Collector} which performs a possibly short-circuiting reduction of its
1967
     * input elements using the provided identity value and a {@code BinaryOperator}.
1968
     *
1969
     * <p>
1970
     * This collector behaves like {@link Collectors#reducing(Object, BinaryOperator)}. However,
1971
     * it additionally accepts a zero element (also known as absorbing element). When zero element
1972
     * is passed to the accumulator then the result must be zero as well. So the collector
1973
     * takes the advantage of this and may short-circuit if zero is reached during the collection.
1974
     *
1975
     * <p>
1976
     * This method returns a
1977
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1978
     * collector</a>: it may not process all the elements if the result of reduction is equal to zero.
1979
     *
1980
     * <p>
1981
     * This collector is mostly useful as a downstream collector. To perform simple
1982
     * short-circuiting reduction, use {@link AbstractStreamEx#reduceWithZero(Object, BinaryOperator)}
1983
     * instead.
1984
     *
1985
     * @param zero zero element
1986
     * @param identity an identity element. For all {@code t}, {@code op.apply(t, identity)} is
1987
     *                 equal to {@code op.apply(identity, t)} and is equal to {@code t}.
1988
     * @param op an <a href="package-summary.html#Associativity">associative</a>
1989
     *        , <a href="package-summary.html#NonInterference">non-interfering
1990
     *        </a>, <a href="package-summary.html#Statelessness">stateless</a>
1991
     *        function to combine two elements into one.
1992
     * @param <T> the type of input elements
1993
     * @return a collector which returns the reduction result.
1994
     * @throws NullPointerException if op is null
1995
     * @see #reducingWithZero(Object, BinaryOperator) 
1996
     * @see AbstractStreamEx#reduceWithZero(Object, Object, BinaryOperator) 
1997
     * @see Collectors#reducing(Object, BinaryOperator) 
1998
     * @since 0.7.3
1999
     */
2000
    public static <T extends @Nullable Object> Collector<T, ?, T> reducingWithZero(T zero, T identity, BinaryOperator<T> op) {
2001
        Objects.requireNonNull(op);
1✔
2002
        // acc.b: 1 = has element, 2 = zero reached
2003
        return new CancellableCollectorImpl<>(
1✔
2004
            () -> new ObjIntBox<>(identity, 1),
1✔
2005
            (acc, t) -> {
2006
                if (acc.b != 2) {
1✔
2007
                    t = op.apply(t, acc.a);
1✔
2008
                    if (Objects.equals(t, zero)) {
1✔
2009
                        acc.b = 2;
1✔
2010
                        acc.a = zero;
1✔
2011
                    } else {
2012
                        acc.b = 1;
1✔
2013
                        acc.a = t;
1✔
2014
                    }
2015
                }
2016
            },
1✔
2017
            (acc1, acc2) -> {
2018
                if (acc2.b == 2) return acc2;
1✔
2019
                if (acc1.b == 2) return acc1;
1✔
2020
                T t = op.apply(acc1.a, acc2.a);
1✔
2021
                if (Objects.equals(t, zero)) {
1✔
2022
                    acc1.b = 2;
1✔
2023
                    acc1.a = zero;
1✔
2024
                } else {
2025
                    acc1.a = t;
1✔
2026
                }
2027
                return acc1;
1✔
2028
            },
2029
            acc -> acc.a,
1✔
2030
            acc -> acc.b == 2,
1✔
2031
            UNORDERED_CHARACTERISTICS
2032
        );
2033
    }
2034
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc