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

amaembo / streamex / #686

19 Jul 2026 09:26AM UTC coverage: 99.777% (-0.02%) from 99.794%
#686

push

amaembo
[#286] EntryStream.withoutKeys and withoutValues don't tolerate streams containing null keys and values respectively

4 of 4 new or added lines in 1 file covered. (100.0%)

4 existing lines in 3 files now uncovered.

5814 of 5827 relevant lines covered (99.78%)

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.NonNull;
19
import org.jspecify.annotations.NullMarked;
20
import org.jspecify.annotations.Nullable;
21

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

© 2026 Coveralls, Inc