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

amaembo / streamex / #673

29 Nov 2023 08:51AM UTC coverage: 99.69%. Remained the same
#673

push

web-flow
Merge pull request #274 from Kivanval/fix/desc

Correcting a comment in StreamEx.java

5787 of 5805 relevant lines covered (99.69%)

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, 2023 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 java.util.ArrayDeque;
19
import java.util.ArrayList;
20
import java.util.Collection;
21
import java.util.Collections;
22
import java.util.Comparator;
23
import java.util.Deque;
24
import java.util.EnumMap;
25
import java.util.EnumSet;
26
import java.util.HashMap;
27
import java.util.HashSet;
28
import java.util.LinkedHashMap;
29
import java.util.List;
30
import java.util.Map;
31
import java.util.Map.Entry;
32
import java.util.Objects;
33
import java.util.Optional;
34
import java.util.OptionalInt;
35
import java.util.OptionalLong;
36
import java.util.Set;
37
import java.util.function.BiConsumer;
38
import java.util.function.BiFunction;
39
import java.util.function.BiPredicate;
40
import java.util.function.BinaryOperator;
41
import java.util.function.Function;
42
import java.util.function.IntFunction;
43
import java.util.function.Predicate;
44
import java.util.function.Supplier;
45
import java.util.function.ToIntFunction;
46
import java.util.function.ToLongFunction;
47
import java.util.stream.Collector;
48
import java.util.stream.Collector.Characteristics;
49
import java.util.stream.Collectors;
50
import java.util.stream.Stream;
51

52
import static one.util.streamex.AbstractStreamEx.addToMap;
53
import static one.util.streamex.Internals.BooleanMap;
54
import static one.util.streamex.Internals.Box;
55
import static one.util.streamex.Internals.CancelException;
56
import static one.util.streamex.Internals.CancellableCollectorImpl;
57
import static one.util.streamex.Internals.ID_CHARACTERISTICS;
58
import static one.util.streamex.Internals.NONE;
59
import static one.util.streamex.Internals.NO_CHARACTERISTICS;
60
import static one.util.streamex.Internals.ObjIntBox;
61
import static one.util.streamex.Internals.PairBox;
62
import static one.util.streamex.Internals.PartialCollector;
63
import static one.util.streamex.Internals.PrimitiveBox;
64
import static one.util.streamex.Internals.UNORDERED_CHARACTERISTICS;
65
import static one.util.streamex.Internals.UNORDERED_ID_CHARACTERISTICS;
66
import static one.util.streamex.Internals.alwaysTrue;
67
import static one.util.streamex.Internals.finished;
68
import static one.util.streamex.Internals.none;
69
import static one.util.streamex.Internals.selectFirst;
70

71
/**
72
 * Implementations of several collectors in addition to ones available in JDK.
73
 * 
74
 * @author Tagir Valeev
75
 * @see Collectors
76
 * @see Joining
77
 * @since 0.3.2
78
 */
79
public final class MoreCollectors {
80
    private MoreCollectors() {
1✔
81
        throw new UnsupportedOperationException();
1✔
82
    }
83

84
    /**
85
     * Returns a {@code Collector} which just ignores the input and calls the
86
     * provided supplier once to return the output.
87
     * 
88
     * @param <T> the type of input elements
89
     * @param <U> the type of output
90
     * @param supplier the supplier of the output
91
     * @return a {@code Collector} which just ignores the input and calls the
92
     *         provided supplier once to return the output.
93
     */
94
    private static <T, U> Collector<T, ?, U> empty(Supplier<U> supplier) {
95
        return new CancellableCollectorImpl<>(() -> NONE, (acc, t) -> {
1✔
96
            // empty
97
        }, selectFirst(), acc -> supplier.get(), alwaysTrue(), EnumSet.of(Characteristics.UNORDERED,
1✔
98
            Characteristics.CONCURRENT));
99
    }
100

101
    private static <T> Collector<T, ?, List<T>> empty() {
102
        return empty(ArrayList<T>::new);
1✔
103
    }
104

105
    /**
106
     * Returns a {@code Collector} that accumulates the input elements into a
107
     * new array.
108
     *
109
     * <p>
110
     * The operation performed by the returned collector is equivalent to
111
     * {@code stream.toArray(generator)}. This collector is mostly useful as a
112
     * downstream collector.
113
     *
114
     * @param <T> the type of the input elements
115
     * @param generator a function which produces a new array of the desired
116
     *        type and the provided length
117
     * @return a {@code Collector} which collects all the input elements into an
118
     *         array, in encounter order
119
     * @throws NullPointerException if generator is null.
120
     */
121
    public static <T> Collector<T, ?, T[]> toArray(IntFunction<T[]> generator) {
122
        Objects.requireNonNull(generator);
1✔
123
        return Collectors.collectingAndThen(Collectors.toList(), list -> list.toArray(generator.apply(list.size())));
1✔
124
    }
125

126
    /**
127
     * Returns a {@code Collector} which produces a boolean array containing the
128
     * results of applying the given predicate to the input elements, in
129
     * encounter order.
130
     * 
131
     * @param <T> the type of the input elements
132
     * @param predicate a non-interfering, stateless predicate to apply to each
133
     *        input element. The result values of this predicate are collected
134
     *        to the resulting boolean array.
135
     * @return a {@code Collector} which collects the results of the predicate
136
     *         function to the boolean array, in encounter order.
137
     * @throws NullPointerException if predicate is null.
138
     * @since 0.3.8
139
     */
140
    public static <T> Collector<T, ?, boolean[]> toBooleanArray(Predicate<T> predicate) {
141
        Objects.requireNonNull(predicate);
1✔
142
        return PartialCollector.booleanArray().asRef((box, t) -> {
1✔
143
            if (predicate.test(t))
1✔
144
                box.a.set(box.b);
1✔
145
            box.b = StrictMath.addExact(box.b, 1);
1✔
146
        });
1✔
147
    }
148

149
    /**
150
     * Returns a {@code Collector} that accumulates the input enum values into a
151
     * new {@code EnumSet}.
152
     *
153
     * <p>
154
     * This method returns a
155
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
156
     * collector</a>: it may not process all the elements if the resulting set
157
     * contains all possible enum values.
158
     * 
159
     * @param <T> the type of the input elements
160
     * @param enumClass the class of input enum values
161
     * @return a {@code Collector} which collects all the input elements into a
162
     *         {@code EnumSet}
163
     * @throws NullPointerException if enumClass is null.
164
     */
165
    public static <T extends Enum<T>> Collector<T, ?, EnumSet<T>> toEnumSet(Class<T> enumClass) {
166
        int size = EnumSet.allOf(enumClass).size();
1✔
167
        return new CancellableCollectorImpl<>(() -> EnumSet.noneOf(enumClass), EnumSet::add, (s1, s2) -> {
1✔
168
            s1.addAll(s2);
1✔
169
            return s1;
1✔
170
        }, Function.identity(), set -> set.size() == size, UNORDERED_ID_CHARACTERISTICS);
1✔
171
    }
172

173
    /**
174
     * Returns a {@code Collector} that accumulates elements into a {@code Map}
175
     * whose keys and values are taken from {@code Map.Entry}.
176
     *
177
     * <p>
178
     * There are no guarantees on the type or serializability of the {@code Map} returned;
179
     * if more control over the returned {@code Map} is required, use {@link #entriesToCustomMap(Supplier)}
180
     *
181
     * <p>
182
     * Returned {@code Map} is guaranteed to be modifiable. See {@link one.util.streamex.EntryStream#toMap()}.
183
     *
184
     * @param <K> the type of the map keys
185
     * @param <V> the type of the map values
186
     * @return {@code Collector} which collects elements into a {@code Map}
187
     * whose keys and values are taken from {@code Map.Entry}
188
     * @throws IllegalStateException if this stream contains duplicate keys
189
     *                               (according to {@link Object#equals(Object)}).
190
     * @see #entriesToMap(BinaryOperator)
191
     * @see Collectors#toMap(Function, Function)
192
     * @since 0.7.3
193
     */
194
    public static <K, V> Collector<Entry<? extends K, ? extends V>, ?, Map<K, V>> entriesToMap() {
195
        return entriesToCustomMap(HashMap::new);
1✔
196
    }
197

198
    /**
199
     * Returns a {@code Collector} that accumulates elements into a {@code Map}
200
     * whose keys and values are taken from {@code Map.Entry} and combining them
201
     * using the provided {@code combiner} function to the input elements.
202
     *
203
     * <p>
204
     * There are no guarantees on the type or serializability of the {@code Map} returned;
205
     * if more control over the returned {@code Map} is required, use {@link #entriesToCustomMap(BinaryOperator, Supplier)}
206
     *
207
     * <p>
208
     * Returned {@code Map} is guaranteed to be modifiable. See {@link one.util.streamex.EntryStream#toMap()}.
209
     *
210
     * <p>If the mapped keys contains duplicates (according to {@link Object#equals(Object)}),
211
     * the value mapping function is applied to each equal element, and the
212
     * results are merged using the provided {@code combiner} function.
213
     *
214
     * @param <K>      the type of the map keys
215
     * @param <V>      the type of the map values
216
     * @param combiner a merge function, used to resolve collisions between
217
     *                 values associated with the same key, as supplied
218
     *                 to {@link Map#merge(Object, Object, BiFunction)}
219
     * @return {@code Collector} which collects elements into a {@code Map}
220
     * whose keys and values are taken from {@code Map.Entry} and combining them
221
     * using the {@code combiner} function
222
     * @throws NullPointerException if combiner is null.
223
     * @see #entriesToMap()
224
     * @see Collectors#toMap(Function, Function, BinaryOperator)
225
     * @since 0.7.3
226
     */
227
    public static <K, V> Collector<Entry<? extends K, ? extends V>, ?, Map<K, V>> entriesToMap(
228
            BinaryOperator<V> combiner) {
229
        return entriesToCustomMap(combiner, HashMap::new);
1✔
230
    }
231

232
    /**
233
     * Returns a {@code Collector} that accumulates elements into
234
     * a result {@code Map} defined by {@code mapSupplier} function
235
     * whose keys and values are taken from {@code Map.Entry}.
236
     *
237
     * @param <K> the type of the map keys
238
     * @param <V> the type of the map values
239
     * @param <M> the type of the resulting {@code Map}
240
     * @param mapSupplier a function which returns a new, empty {@code Map} into
241
     *                    which the results will be inserted
242
     * @return {@code Collector} which collects elements into a {@code Map}
243
     * defined by {@code mapSupplier} function
244
     * whose keys and values are taken from {@code Map.Entry}
245
     * @throws IllegalStateException if this stream contains duplicate keys
246
     *                               (according to {@link Object#equals(Object)}).
247
     * @throws NullPointerException  if mapSupplier is null.
248
     * @throws NullPointerException  if entry value is null.
249
     * @see #entriesToCustomMap(BinaryOperator, Supplier)
250
     * @see Collector#of(Supplier, BiConsumer, BinaryOperator, Collector.Characteristics...)
251
     * @since 0.7.3
252
     */
253
    public static <K, V, M extends Map<K, V>> Collector<Entry<? extends K, ? extends V>, ?, M> entriesToCustomMap(
254
            Supplier<M> mapSupplier) {
255
        return Collector.of(mapSupplier,
1✔
256
                (m, entry) -> addToMap(m, entry.getKey(), Objects.requireNonNull(entry.getValue())),
1✔
257
                (m1, m2) -> {
258
                    m2.forEach((k, v) -> addToMap(m1, k, v));
1✔
259
                    return m1;
1✔
260
                }
261
        );
262
    }
263

264
    /**
265
     * Returns a {@code Collector} that accumulates elements into
266
     * a result {@code Map} defined by {@code mapSupplier} function
267
     * whose keys and values are taken from {@code Map.Entry} and combining them
268
     * using the provided {@code combiner} function to the input elements.
269
     *
270
     * <p>If the mapped keys contains duplicates (according to {@link Object#equals(Object)}),
271
     * the value mapping function is applied to each equal element, and the
272
     * results are merged using the provided {@code combiner} function.
273
     *
274
     * @param <K>         the type of the map keys
275
     * @param <V>         the type of the map values
276
     * @param <M>         the type of the resulting {@code Map}
277
     * @param combiner    a merge function, used to resolve collisions between
278
     *                    values associated with the same key, as supplied
279
     *                    to {@link Map#merge(Object, Object, BiFunction)}
280
     * @param mapSupplier a function which returns a new, empty {@code Map} into
281
     *                    which the results will be inserted
282
     * @return {@code Collector} which collects elements into a {@code Map}
283
     * whose keys and values are taken from {@code Map.Entry} and combining them
284
     * using the {@code combiner} function
285
     * @throws NullPointerException if {@code combiner} is null.
286
     * @throws NullPointerException if {@code mapSupplier} is null.
287
     * @see #entriesToCustomMap(Supplier)
288
     * @see Collectors#toMap(Function, Function, BinaryOperator, Supplier)
289
     * @since 0.7.3
290
     */
291
    public static <K, V, M extends Map<K, V>> Collector<Entry<? extends K, ? extends V>, ?, M> entriesToCustomMap(
292
            BinaryOperator<V> combiner, Supplier<M> mapSupplier) {
293
        Objects.requireNonNull(combiner);
1✔
294
        Objects.requireNonNull(mapSupplier);
1✔
295
        return Collectors.toMap(Entry::getKey, Entry::getValue, combiner, mapSupplier);
1✔
296
    }
297

298
    /**
299
     * Returns a {@code Collector} which counts a number of distinct values the
300
     * mapper function returns for the stream elements.
301
     * 
302
     * <p>
303
     * The operation performed by the returned collector is equivalent to
304
     * {@code stream.map(mapper).distinct().count()}. This collector is mostly
305
     * useful as a downstream collector.
306
     * 
307
     * @param <T> the type of the input elements
308
     * @param mapper a function which classifies input elements.
309
     * @return a collector which counts a number of distinct classes the mapper
310
     *         function returns for the stream elements.
311
     * @throws NullPointerException if mapper is null.
312
     */
313
    public static <T> Collector<T, ?, Integer> distinctCount(Function<? super T, ?> mapper) {
314
        Objects.requireNonNull(mapper);
1✔
315
        return Collectors.collectingAndThen(Collectors.mapping(mapper, Collectors.toSet()), Set::size);
1✔
316
    }
317

318
    /**
319
     * Returns a {@code Collector} which collects into the {@link List} the
320
     * input elements for which given mapper function returns distinct results.
321
     *
322
     * <p>
323
     * For ordered source the order of collected elements is preserved. If the
324
     * same result is returned by mapper function for several elements, only the
325
     * first element is included into the resulting list.
326
     * 
327
     * <p>
328
     * There are no guarantees on the type, mutability, serializability, or
329
     * thread-safety of the {@code List} returned.
330
     * 
331
     * <p>
332
     * The operation performed by the returned collector is equivalent to
333
     * {@code stream.distinct(mapper).toList()}, but may work faster.
334
     * 
335
     * @param <T> the type of the input elements
336
     * @param mapper a function which classifies input elements.
337
     * @return a collector which collects distinct elements to the {@code List}.
338
     * @throws NullPointerException if mapper is null.
339
     * @since 0.3.8
340
     */
341
    public static <T> Collector<T, ?, List<T>> distinctBy(Function<? super T, ?> mapper) {
342
        Objects.requireNonNull(mapper);
1✔
343
        return Collector.<T, Map<Object, T>, List<T>>of(LinkedHashMap::new, (map, t) -> map.putIfAbsent(mapper.apply(
1✔
344
            t), t), (m1, m2) -> {
345
                for (Entry<Object, T> e : m2.entrySet()) {
1✔
346
                    m1.putIfAbsent(e.getKey(), e.getValue());
1✔
347
                }
1✔
348
                return m1;
1✔
349
            }, map -> new ArrayList<>(map.values()));
1✔
350
    }
351

352
    /**
353
     * Returns a {@code Collector} accepting elements of type {@code T} that
354
     * counts the number of input elements and returns result as {@code Integer}
355
     * . If no elements are present, the result is 0.
356
     *
357
     * @param <T> the type of the input elements
358
     * @return a {@code Collector} that counts the input elements
359
     * @since 0.3.3
360
     * @see Collectors#counting()
361
     */
362
    public static <T> Collector<T, ?, Integer> countingInt() {
363
        return PartialCollector.intSum().asRef((acc, t) -> acc[0]++);
1✔
364
    }
365

366
    /**
367
     * Returns a {@code Collector} which aggregates the results of two supplied
368
     * collectors using the supplied finisher function.
369
     * 
370
     * <p>
371
     * This method returns a
372
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
373
     * collector</a> if both downstream collectors are short-circuiting. The
374
     * collection might stop when both downstream collectors report that the
375
     * collection is complete.
376
     * 
377
     * <p>
378
     * This collector is similar to the {@code teeing} collector available since
379
     * JDK 12. The only difference is that this collector correctly combines 
380
     * short-circuiting collectors.
381
     * 
382
     * @param <T> the type of the input elements
383
     * @param <A1> the intermediate accumulation type of the first collector
384
     * @param <A2> the intermediate accumulation type of the second collector
385
     * @param <R1> the result type of the first collector
386
     * @param <R2> the result type of the second collector
387
     * @param <R> the final result type
388
     * @param c1 the first collector
389
     * @param c2 the second collector
390
     * @param finisher the function which merges two results into the single
391
     *        one.
392
     * @return a {@code Collector} which aggregates the results of two supplied
393
     *         collectors.
394
     * @throws NullPointerException if c1 is null, or c2 is null, or finisher is null.
395
     */
396
    public static <T, A1, A2, R1, R2, R> Collector<T, ?, R> pairing(Collector<? super T, A1, R1> c1,
397
            Collector<? super T, A2, R2> c2, BiFunction<? super R1, ? super R2, ? extends R> finisher) {
398
        Objects.requireNonNull(finisher);
1✔
399
        EnumSet<Characteristics> c = EnumSet.noneOf(Characteristics.class);
1✔
400
        c.addAll(c1.characteristics());
1✔
401
        c.retainAll(c2.characteristics());
1✔
402
        c.remove(Characteristics.IDENTITY_FINISH);
1✔
403

404
        Supplier<A1> c1Supplier = c1.supplier();
1✔
405
        Supplier<A2> c2Supplier = c2.supplier();
1✔
406
        BiConsumer<A1, ? super T> c1Accumulator = c1.accumulator();
1✔
407
        BiConsumer<A2, ? super T> c2Accumulator = c2.accumulator();
1✔
408
        BinaryOperator<A1> c1Combiner = c1.combiner();
1✔
409
        BinaryOperator<A2> c2combiner = c2.combiner();
1✔
410

411
        Supplier<PairBox<A1, A2>> supplier = () -> new PairBox<>(c1Supplier.get(), c2Supplier.get());
1✔
412
        BiConsumer<PairBox<A1, A2>, T> accumulator = (acc, v) -> {
1✔
413
            c1Accumulator.accept(acc.a, v);
1✔
414
            c2Accumulator.accept(acc.b, v);
1✔
415
        };
1✔
416
        BinaryOperator<PairBox<A1, A2>> combiner = (acc1, acc2) -> {
1✔
417
            acc1.a = c1Combiner.apply(acc1.a, acc2.a);
1✔
418
            acc1.b = c2combiner.apply(acc1.b, acc2.b);
1✔
419
            return acc1;
1✔
420
        };
421
        Function<PairBox<A1, A2>, R> resFinisher = acc -> {
1✔
422
            R1 r1 = c1.finisher().apply(acc.a);
1✔
423
            R2 r2 = c2.finisher().apply(acc.b);
1✔
424
            return finisher.apply(r1, r2);
1✔
425
        };
426
        Predicate<A1> c1Finished = finished(c1);
1✔
427
        Predicate<A2> c2Finished = finished(c2);
1✔
428
        if (c1Finished != null && c2Finished != null) {
1✔
429
            Predicate<PairBox<A1, A2>> finished = acc -> c1Finished.test(acc.a) && c2Finished.test(acc.b);
1✔
430
            return new CancellableCollectorImpl<>(supplier, accumulator, combiner, resFinisher, finished, c);
1✔
431
        }
432
        return Collector.of(supplier, accumulator, combiner, resFinisher, c.toArray(new Characteristics[0]));
1✔
433
    }
434

435
    /**
436
     * Returns a {@code Collector} which finds the minimal and maximal element
437
     * according to the supplied comparator, then applies finisher function to
438
     * them producing the final result.
439
     * 
440
     * <p>
441
     * This collector produces stable result for ordered stream: if several
442
     * minimal or maximal elements appear, the collector always selects the
443
     * first encountered.
444
     * 
445
     * <p>
446
     * If there are no input elements, the finisher method is not called and
447
     * empty {@code Optional} is returned. Otherwise the finisher result is
448
     * wrapped into {@code Optional}.
449
     *
450
     * @param <T> the type of the input elements
451
     * @param <R> the type of the result wrapped into {@code Optional}
452
     * @param comparator comparator which is used to find minimal and maximal
453
     *        element
454
     * @param finisher a {@link BiFunction} which takes minimal and maximal
455
     *        element and produces the final result.
456
     * @return a {@code Collector} which finds minimal and maximal elements.
457
     * @throws NullPointerException if comparator is null, finisher is null,
458
     * or finisher returns null.
459
     */
460
    public static <T, R> Collector<T, ?, Optional<R>> minMax(Comparator<? super T> comparator,
461
            BiFunction<? super T, ? super T, ? extends R> finisher) {
462
        Objects.requireNonNull(finisher);
1✔
463
        return pairing(Collectors.minBy(comparator), Collectors.maxBy(comparator),
1✔
464
            (min, max) -> min.isPresent() ? Optional.of(finisher.apply(min.get(), max.get())) : Optional.empty());
1✔
465
    }
466

467
    /**
468
     * Returns a {@code Collector} which finds all the elements which are equal
469
     * to each other and bigger than any other element according to the
470
     * specified {@link Comparator}. The found elements are reduced using the
471
     * specified downstream {@code Collector}.
472
     *
473
     * @param <T> the type of the input elements
474
     * @param <A> the intermediate accumulation type of the downstream collector
475
     * @param <D> the result type of the downstream reduction
476
     * @param comparator a {@code Comparator} to compare the elements
477
     * @param downstream a {@code Collector} implementing the downstream
478
     *        reduction
479
     * @return a {@code Collector} which finds all the maximal elements.
480
     * @throws NullPointerException if comparator is null, or downstream is null.
481
     * @see #maxAll(Comparator)
482
     * @see #maxAll(Collector)
483
     * @see #maxAll()
484
     */
485
    public static <T, A, D> Collector<T, ?, D> maxAll(Comparator<? super T> comparator,
486
            Collector<? super T, A, D> downstream) {
487
        Objects.requireNonNull(comparator);
1✔
488
        Supplier<A> downstreamSupplier = downstream.supplier();
1✔
489
        BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
1✔
490
        BinaryOperator<A> downstreamCombiner = downstream.combiner();
1✔
491
        Supplier<PairBox<A, T>> supplier = () -> new PairBox<>(downstreamSupplier.get(), none());
1✔
492
        BiConsumer<PairBox<A, T>, T> accumulator = (acc, t) -> {
1✔
493
            if (acc.b == NONE) {
1✔
494
                downstreamAccumulator.accept(acc.a, t);
1✔
495
                acc.b = t;
1✔
496
            } else {
497
                int cmp = comparator.compare(t, acc.b);
1✔
498
                if (cmp > 0) {
1✔
499
                    acc.a = downstreamSupplier.get();
1✔
500
                    acc.b = t;
1✔
501
                }
502
                if (cmp >= 0)
1✔
503
                    downstreamAccumulator.accept(acc.a, t);
1✔
504
            }
505
        };
1✔
506
        BinaryOperator<PairBox<A, T>> combiner = (acc1, acc2) -> {
1✔
507
            if (acc2.b == NONE) {
1✔
508
                return acc1;
1✔
509
            }
510
            if (acc1.b == NONE) {
1✔
511
                return acc2;
1✔
512
            }
513
            int cmp = comparator.compare(acc1.b, acc2.b);
1✔
514
            if (cmp > 0) {
1✔
515
                return acc1;
1✔
516
            }
517
            if (cmp < 0) {
1✔
518
                return acc2;
1✔
519
            }
520
            acc1.a = downstreamCombiner.apply(acc1.a, acc2.a);
1✔
521
            return acc1;
1✔
522
        };
523
        Function<PairBox<A, T>, D> finisher = acc -> downstream.finisher().apply(acc.a);
1✔
524
        return Collector.of(supplier, accumulator, combiner, finisher);
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
530
     * specified {@link Comparator}. The found elements are collected to
531
     * {@link List}.
532
     *
533
     * @param <T> the type of the input elements
534
     * @param comparator a {@code Comparator} to compare the elements
535
     * @return a {@code Collector} which finds all the maximal elements and
536
     *         collects them to the {@code List}.
537
     * @throws NullPointerException if comparator is null.
538
     * @see #maxAll(Comparator, Collector)
539
     * @see #maxAll()
540
     */
541
    public static <T> Collector<T, ?, List<T>> maxAll(Comparator<? super T> comparator) {
542
        return maxAll(comparator, Collectors.toList());
1✔
543
    }
544

545
    /**
546
     * Returns a {@code Collector} which finds all the elements which are equal
547
     * to each other and bigger than any other element according to the natural
548
     * order. The found elements are reduced using the specified downstream
549
     * {@code Collector}.
550
     *
551
     * @param <T> the type of the input elements
552
     * @param <A> the intermediate accumulation type of the downstream collector
553
     * @param <D> the result type of the downstream reduction
554
     * @param downstream a {@code Collector} implementing the downstream
555
     *        reduction
556
     * @return a {@code Collector} which finds all the maximal elements.
557
     * @throws NullPointerException if downstream is null.
558
     * @see #maxAll(Comparator, Collector)
559
     * @see #maxAll(Comparator)
560
     * @see #maxAll()
561
     */
562
    public static <T extends Comparable<? super T>, A, D> Collector<T, ?, D> maxAll(Collector<T, A, D> downstream) {
563
        return maxAll(Comparator.<T>naturalOrder(), downstream);
1✔
564
    }
565

566
    /**
567
     * Returns a {@code Collector} which finds all the elements which are equal
568
     * to each other and bigger than any other element according to the natural
569
     * order. The found elements are collected to {@link List}.
570
     *
571
     * @param <T> the type of the input elements
572
     * @return a {@code Collector} which finds all the maximal elements and
573
     *         collects them to the {@code List}.
574
     * @see #maxAll(Comparator)
575
     * @see #maxAll(Collector)
576
     */
577
    public static <T extends Comparable<? super T>> Collector<T, ?, List<T>> maxAll() {
578
        return maxAll(Comparator.<T>naturalOrder(), Collectors.toList());
1✔
579
    }
580

581
    /**
582
     * Returns a {@code Collector} which finds all the elements which are equal
583
     * to each other and smaller than any other element according to the
584
     * specified {@link Comparator}. The found elements are reduced using the
585
     * specified downstream {@code Collector}.
586
     *
587
     * @param <T> the type of the input elements
588
     * @param <A> the intermediate accumulation type of the downstream collector
589
     * @param <D> the result type of the downstream reduction
590
     * @param comparator a {@code Comparator} to compare the elements
591
     * @param downstream a {@code Collector} implementing the downstream
592
     *        reduction
593
     * @return a {@code Collector} which finds all the minimal elements.
594
     * @throws NullPointerException if comparator is null, or downstream is null.
595
     * @see #minAll(Comparator)
596
     * @see #minAll(Collector)
597
     * @see #minAll()
598
     */
599
    public static <T, A, D> Collector<T, ?, D> minAll(Comparator<? super T> comparator, Collector<T, A, D> downstream) {
600
        return maxAll(comparator.reversed(), downstream);
1✔
601
    }
602

603
    /**
604
     * Returns a {@code Collector} which finds all the elements which are equal
605
     * to each other and smaller than any other element according to the
606
     * specified {@link Comparator}. The found elements are collected to
607
     * {@link List}.
608
     *
609
     * @param <T> the type of the input elements
610
     * @param comparator a {@code Comparator} to compare the elements
611
     * @return a {@code Collector} which finds all the minimal elements and
612
     *         collects them to the {@code List}.
613
     * @throws NullPointerException if comparator is null.
614
     * @see #minAll(Comparator, Collector)
615
     * @see #minAll()
616
     */
617
    public static <T> Collector<T, ?, List<T>> minAll(Comparator<? super T> comparator) {
618
        return maxAll(comparator.reversed(), Collectors.toList());
1✔
619
    }
620

621
    /**
622
     * Returns a {@code Collector} which finds all the elements which are equal
623
     * to each other and smaller than any other element according to the natural
624
     * order. The found elements are reduced using the specified downstream
625
     * {@code Collector}.
626
     *
627
     * @param <T> the type of the input elements
628
     * @param <A> the intermediate accumulation type of the downstream collector
629
     * @param <D> the result type of the downstream reduction
630
     * @param downstream a {@code Collector} implementing the downstream
631
     *        reduction
632
     * @return a {@code Collector} which finds all the minimal elements.
633
     * @throws NullPointerException if downstream is null.
634
     * @see #minAll(Comparator, Collector)
635
     * @see #minAll(Comparator)
636
     * @see #minAll()
637
     */
638
    public static <T extends Comparable<? super T>, A, D> Collector<T, ?, D> minAll(Collector<T, A, D> downstream) {
639
        return maxAll(Comparator.<T>reverseOrder(), downstream);
1✔
640
    }
641

642
    /**
643
     * Returns a {@code Collector} which finds all the elements which are equal
644
     * to each other and smaller than any other element according to the natural
645
     * order. The found elements are collected to {@link List}.
646
     *
647
     * @param <T> the type of the input elements
648
     * @return a {@code Collector} which finds all the minimal elements and
649
     *         collects them to the {@code List}.
650
     * @see #minAll(Comparator)
651
     * @see #minAll(Collector)
652
     */
653
    public static <T extends Comparable<? super T>> Collector<T, ?, List<T>> minAll() {
654
        return maxAll(Comparator.<T>reverseOrder(), Collectors.toList());
1✔
655
    }
656

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

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

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

729
    /**
730
     * Returns a {@code Collector} which collects only the last stream element
731
     * if any.
732
     * 
733
     * @param <T> the type of the input elements
734
     * @return a collector which returns an {@link Optional} which describes the
735
     *         last element of the stream. For empty stream an empty
736
     *         {@code Optional} is returned.
737
     * @throws NullPointerException if the last stream element is null.
738
     */
739
    public static <T> Collector<T, ?, Optional<T>> last() {
740
        return Collector.of(() -> new Box<T>(none()), (box, t) -> box.a = t,
1✔
741
            (box1, box2) -> box2.a == NONE ? box1 : box2, box -> box.a == NONE ? Optional.empty() : Optional.of(box.a));
1✔
742
    }
743

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

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

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

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

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

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

961
    /**
962
     * Returns a {@code Collector} which finds the index of the minimal stream
963
     * element according to the specified {@link Comparator}. If there are
964
     * several minimal elements, the index of the first one is returned.
965
     *
966
     * @param <T> the type of the input elements
967
     * @param comparator a {@code Comparator} to compare the elements
968
     * @return a {@code Collector} which finds the index of the minimal element.
969
     * @throws NullPointerException if comparator is null.
970
     * @see #minIndex()
971
     * @since 0.3.5
972
     */
973
    public static <T> Collector<T, ?, OptionalLong> minIndex(Comparator<? super T> comparator) {
974
        Objects.requireNonNull(comparator);
1✔
975
        class Container {
1✔
976
            T value;
977
            long count = 0;
1✔
978
            long index = -1;
1✔
979
        }
980

981
        return Collector.of(Container::new, (c, t) -> {
1✔
982
            if (c.index == -1 || comparator.compare(c.value, t) > 0) {
1✔
983
                c.value = t;
1✔
984
                c.index = c.count;
1✔
985
            }
986
            c.count++;
1✔
987
        }, (c1, c2) -> {
1✔
988
            if (c1.index == -1 || (c2.index != -1 && comparator.compare(c1.value, c2.value) > 0)) {
1✔
989
                c2.index += c1.count;
1✔
990
                c2.count += c1.count;
1✔
991
                return c2;
1✔
992
            }
993
            c1.count += c2.count;
1✔
994
            return c1;
1✔
995
        }, c -> c.index == -1 ? OptionalLong.empty() : OptionalLong.of(c.index));
1✔
996
    }
997

998
    /**
999
     * Returns a {@code Collector} which finds the index of the minimal stream
1000
     * element according to the elements natural order. If there are several
1001
     * minimal elements, the index of the first one is returned.
1002
     *
1003
     * @param <T> the type of the input elements
1004
     * @return a {@code Collector} which finds the index of the minimal element.
1005
     * @see #minIndex(Comparator)
1006
     * @since 0.3.5
1007
     */
1008
    public static <T extends Comparable<? super T>> Collector<T, ?, OptionalLong> minIndex() {
1009
        return minIndex(Comparator.naturalOrder());
1✔
1010
    }
1011

1012
    /**
1013
     * Returns a {@code Collector} which finds the index of the maximal stream
1014
     * element according to the specified {@link Comparator}. If there are
1015
     * several maximal elements, the index of the first one is returned.
1016
     *
1017
     * @param <T> the type of the input elements
1018
     * @param comparator a {@code Comparator} to compare the elements
1019
     * @return a {@code Collector} which finds the index of the maximal element.
1020
     * @throws NullPointerException if comparator is null.
1021
     * @see #maxIndex()
1022
     * @since 0.3.5
1023
     */
1024
    public static <T> Collector<T, ?, OptionalLong> maxIndex(Comparator<? super T> comparator) {
1025
        return minIndex(comparator.reversed());
1✔
1026
    }
1027

1028
    /**
1029
     * Returns a {@code Collector} which finds the index of the maximal stream
1030
     * element according to the elements natural order. If there are several
1031
     * maximal elements, the index of the first one is returned.
1032
     *
1033
     * @param <T> the type of the input elements
1034
     * @return a {@code Collector} which finds the index of the maximal element.
1035
     * @see #maxIndex(Comparator)
1036
     * @since 0.3.5
1037
     */
1038
    public static <T extends Comparable<? super T>> Collector<T, ?, OptionalLong> maxIndex() {
1039
        return minIndex(Comparator.reverseOrder());
1✔
1040
    }
1041

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

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

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

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

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

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

1331
    /**
1332
     * Adapts a {@code Collector} accepting elements of type {@code U} to one
1333
     * accepting elements of type {@code T} by applying a mapping function to
1334
     * each input element before accumulation.
1335
     *
1336
     * <p>
1337
     * Unlike {@link Collectors#mapping(Function, Collector)} this method
1338
     * returns a
1339
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1340
     * collector</a> if the downstream collector is short-circuiting.
1341
     * 
1342
     * @param <T> the type of the input elements
1343
     * @param <U> type of elements accepted by downstream collector
1344
     * @param <A> intermediate accumulation type of the downstream collector
1345
     * @param <R> result type of collector
1346
     * @param mapper a function to be applied to the input elements
1347
     * @param downstream a collector which will accept mapped values
1348
     * @return a collector which applies the mapping function to the input
1349
     *         elements and provides the mapped results to the downstream
1350
     *         collector
1351
     * @throws NullPointerException if mapper is null, or downstream is null.
1352
     * @see Collectors#mapping(Function, Collector)
1353
     * @since 0.4.0
1354
     */
1355
    public static <T, U, A, R> Collector<T, ?, R> mapping(Function<? super T, ? extends U> mapper,
1356
            Collector<? super U, A, R> downstream) {
1357
        Objects.requireNonNull(mapper);
1✔
1358
        Predicate<A> finished = finished(downstream);
1✔
1359
        if (finished != null) {
1✔
1360
            BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator();
1✔
1361
            return new CancellableCollectorImpl<>(downstream.supplier(), (acc, t) -> {
1✔
1362
                if (!finished.test(acc))
1✔
1363
                    downstreamAccumulator.accept(acc, mapper.apply(t));
1✔
1364
            }, downstream.combiner(), downstream.finisher(), finished, downstream.characteristics());
1✔
1365
        }
1366
        return Collectors.mapping(mapper, downstream);
1✔
1367
    }
1368

1369
    /**
1370
     * Returns a collector which collects input elements to the new {@code List}
1371
     * transforming them with the supplied function beforehand.
1372
     * 
1373
     * <p>
1374
     * This method behaves like
1375
     * {@code Collectors.mapping(mapper, Collectors.toList())}.
1376
     * 
1377
     * <p>
1378
     * There are no guarantees on the type, mutability, serializability, or
1379
     * thread-safety of the {@code List} returned.
1380
     * 
1381
     * @param <T> the type of the input elements
1382
     * @param <U> the resulting type of the mapper function
1383
     * @param mapper a function to be applied to the input elements
1384
     * @return a collector which applies the mapping function to the input
1385
     *         elements and collects the mapped results to the {@code List}
1386
     * @throws NullPointerException if mapper is null.
1387
     * @see #mapping(Function, Collector)
1388
     * @since 0.6.0
1389
     */
1390
    public static <T, U> Collector<T, ?, List<U>> mapping(Function<? super T, ? extends U> mapper) {
1391
        return Collectors.mapping(mapper, Collectors.toList());
1✔
1392
    }
1393

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

1455
    /**
1456
     * Returns a collector which launches a flat mapping function for each input
1457
     * element and collects the elements of the resulting streams to the flat
1458
     * {@code List}. Each mapped stream is
1459
     * {@link java.util.stream.BaseStream#close() closed} after its contents
1460
     * have been placed downstream. (If a mapped stream is {@code null} an empty
1461
     * stream is used, instead.)
1462
     * 
1463
     * <p>
1464
     * This method behaves like {@code flatMapping(mapper, Collectors.toList())}
1465
     * .
1466
     * 
1467
     * <p>
1468
     * There are no guarantees on the type, mutability, serializability, or
1469
     * thread-safety of the {@code List} returned.
1470
     * 
1471
     * @param <T> the type of the input elements
1472
     * @param <U> type of the resulting elements
1473
     * @param mapper a function to be applied to the input elements, which
1474
     *        returns a stream of results
1475
     * @return a collector which applies the mapping function to the input
1476
     *         elements and collects the flat mapped results to the {@code List}
1477
     * @throws NullPointerException if mapper is null.
1478
     * @since 0.6.0
1479
     */
1480
    public static <T, U> Collector<T, ?, List<U>> flatMapping(
1481
            Function<? super T, ? extends Stream<? extends U>> mapper) {
1482
        return flatMapping(mapper, Collectors.toList());
1✔
1483
    }
1484

1485
    /**
1486
     * Returns a {@code Collector} which passes only those elements to the
1487
     * specified downstream collector which match given predicate.
1488
     *
1489
     * <p>
1490
     * This method returns a
1491
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1492
     * collector</a> if downstream collector is short-circuiting.
1493
     * 
1494
     * <p>
1495
     * The operation performed by the returned collector is equivalent to
1496
     * {@code stream.filter(predicate).collect(downstream)}. This collector is
1497
     * mostly useful as a downstream collector in cascaded operation involving
1498
     * {@link #pairing(Collector, Collector, BiFunction)} collector.
1499
     *
1500
     * <p>
1501
     * This method is similar to {@code Collectors.filtering} method which
1502
     * appears in JDK 9. However when downstream collector is
1503
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting</a>
1504
     * , this method will also return a short-circuiting collector.
1505
     * 
1506
     * @param <T> the type of the input elements
1507
     * @param <A> intermediate accumulation type of the downstream collector
1508
     * @param <R> result type of collector
1509
     * @param predicate a filter function to be applied to the input elements
1510
     * @param downstream a collector which will accept filtered values
1511
     * @return a collector which applies the predicate to the input elements and
1512
     *         provides the elements for which predicate returned true to the
1513
     *         downstream collector
1514
     * @throws NullPointerException if predicate is null, or downstream is null.
1515
     * @see #pairing(Collector, Collector, BiFunction)
1516
     * @since 0.4.0
1517
     */
1518
    public static <T, A, R> Collector<T, ?, R> filtering(Predicate<? super T> predicate,
1519
            Collector<T, A, R> downstream) {
1520
        Objects.requireNonNull(predicate);
1✔
1521
        BiConsumer<A, T> downstreamAccumulator = downstream.accumulator();
1✔
1522
        BiConsumer<A, T> accumulator = (acc, t) -> {
1✔
1523
            if (predicate.test(t))
1✔
1524
                downstreamAccumulator.accept(acc, t);
1✔
1525
        };
1✔
1526
        Predicate<A> finished = finished(downstream);
1✔
1527
        if (finished != null) {
1✔
1528
            return new CancellableCollectorImpl<>(downstream.supplier(), accumulator, downstream.combiner(), downstream
1✔
1529
                    .finisher(), finished, downstream.characteristics());
1✔
1530
        }
1531
        return Collector.of(downstream.supplier(), accumulator, downstream.combiner(), downstream.finisher(), downstream
1✔
1532
                .characteristics().toArray(new Characteristics[0]));
1✔
1533
    }
1534

1535
    /**
1536
     * Returns a {@code Collector} which filters input elements by the supplied
1537
     * predicate, collecting them to the list.
1538
     *
1539
     * <p>
1540
     * This method behaves like
1541
     * {@code filtering(predicate, Collectors.toList())}.
1542
     * 
1543
     * <p>
1544
     * There are no guarantees on the type, mutability, serializability, or
1545
     * thread-safety of the {@code List} returned.
1546
     * 
1547
     * @param <T> the type of the input elements
1548
     * @param predicate a filter function to be applied to the input elements
1549
     * @return a collector which applies the predicate to the input elements and
1550
     *         collects the elements for which predicate returned true to the
1551
     *         {@code List}
1552
     * @throws NullPointerException if predicate is null.
1553
     * @see #filtering(Predicate, Collector)
1554
     * @since 0.6.0
1555
     */
1556
    public static <T> Collector<T, ?, List<T>> filtering(Predicate<? super T> predicate) {
1557
        return filtering(predicate, Collectors.toList());
1✔
1558
    }
1559

1560
    /**
1561
     * Returns a {@code Collector} which performs the bitwise-and operation of a
1562
     * integer-valued function applied to the input elements. If no elements are
1563
     * present, the result is empty {@link OptionalInt}.
1564
     *
1565
     * <p>
1566
     * This method returns a
1567
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1568
     * collector</a>: it may not process all the elements if the result is zero.
1569
     * 
1570
     * @param <T> the type of the input elements
1571
     * @param mapper a function extracting the property to be processed
1572
     * @return a {@code Collector} that produces the bitwise-and operation of a
1573
     *         derived property
1574
     * @throws NullPointerException if mapper is null.
1575
     * @since 0.4.0
1576
     */
1577
    public static <T> Collector<T, ?, OptionalInt> andingInt(ToIntFunction<T> mapper) {
1578
        Objects.requireNonNull(mapper);
1✔
1579
        return new CancellableCollectorImpl<>(PrimitiveBox::new, (acc, t) -> {
1✔
1580
            if (!acc.b) {
1✔
1581
                acc.i = mapper.applyAsInt(t);
1✔
1582
                acc.b = true;
1✔
1583
            } else {
1584
                acc.i &= mapper.applyAsInt(t);
1✔
1585
            }
1586
        }, (acc1, acc2) -> {
1✔
1587
            if (!acc1.b)
1✔
1588
                return acc2;
1✔
1589
            if (!acc2.b)
1✔
1590
                return acc1;
1✔
1591
            acc1.i &= acc2.i;
1✔
1592
            return acc1;
1✔
1593
        }, PrimitiveBox::asInt, acc -> acc.b && acc.i == 0, UNORDERED_CHARACTERISTICS);
1✔
1594
    }
1595

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

1632
    /**
1633
     * Returns a {@code Collector} which computes a common prefix of input
1634
     * {@code CharSequence} objects returning the result as {@code String}. For
1635
     * empty input the empty {@code String} is returned.
1636
     *
1637
     * <p>
1638
     * The returned {@code Collector} handles specially Unicode surrogate pairs:
1639
     * the returned prefix may end with
1640
     * <a href="http://www.unicode.org/glossary/#high_surrogate_code_unit">
1641
     * Unicode high-surrogate code unit</a> only if it's not succeeded by
1642
     * <a href="http://www.unicode.org/glossary/#low_surrogate_code_unit">
1643
     * Unicode low-surrogate code unit</a> in any of the input sequences.
1644
     * Normally the ending high-surrogate code unit is removed from the prefix.
1645
     * 
1646
     * <p>
1647
     * This method returns a
1648
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1649
     * collector</a>: it may not process all the elements if the common prefix
1650
     * is empty.
1651
     * 
1652
     * @return a {@code Collector} which computes a common prefix.
1653
     * @since 0.5.0
1654
     */
1655
    public static Collector<CharSequence, ?, String> commonPrefix() {
1656
        BiConsumer<ObjIntBox<CharSequence>, CharSequence> accumulator = (acc, t) -> {
1✔
1657
            if (acc.b == -1) {
1✔
1658
                acc.a = t;
1✔
1659
                acc.b = t.length();
1✔
1660
            } else if (acc.b > 0) {
1✔
1661
                if (t.length() < acc.b)
1✔
1662
                    acc.b = t.length();
1✔
1663
                for (int i = 0; i < acc.b; i++) {
1✔
1664
                    if (acc.a.charAt(i) != t.charAt(i)) {
1✔
1665
                        if (i > 0 && Character.isHighSurrogate(t.charAt(i - 1)) && (Character.isLowSurrogate(t.charAt(
1✔
1666
                            i)) || Character.isLowSurrogate(acc.a.charAt(i))))
1✔
1667
                            i--;
1✔
1668
                        acc.b = i;
1✔
1669
                        break;
1✔
1670
                    }
1671
                }
1672
            }
1673
        };
1✔
1674
        return new CancellableCollectorImpl<>(() -> new ObjIntBox<>(null, -1), accumulator, (acc1, acc2) -> {
1✔
1675
            if (acc1.b == -1)
1✔
1676
                return acc2;
1✔
1677
            if (acc2.b != -1)
1✔
1678
                accumulator.accept(acc1, acc2.a.subSequence(0, acc2.b));
1✔
1679
            return acc1;
1✔
1680
        }, acc -> acc.a == null ? "" : acc.a.subSequence(0, acc.b).toString(), acc -> acc.b == 0,
1✔
1681
                UNORDERED_CHARACTERISTICS);
1682
    }
1683

1684
    /**
1685
     * Returns a {@code Collector} which computes a common suffix of input
1686
     * {@code CharSequence} objects returning the result as {@code String}. For
1687
     * empty input the empty {@code String} is returned.
1688
     *
1689
     * <p>
1690
     * The returned {@code Collector} handles specially Unicode surrogate pairs:
1691
     * the returned suffix may start with
1692
     * <a href="http://www.unicode.org/glossary/#low_surrogate_code_unit">
1693
     * Unicode low-surrogate code unit</a> only if it's not preceded by
1694
     * <a href="http://www.unicode.org/glossary/#high_surrogate_code_unit">
1695
     * Unicode high-surrogate code unit</a> in any of the input sequences.
1696
     * Normally the starting low-surrogate code unit is removed from the suffix.
1697
     * 
1698
     * <p>
1699
     * This method returns a
1700
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1701
     * collector</a>: it may not process all the elements if the common suffix
1702
     * is empty.
1703
     * 
1704
     * @return a {@code Collector} which computes a common suffix.
1705
     * @since 0.5.0
1706
     */
1707
    public static Collector<CharSequence, ?, String> commonSuffix() {
1708
        BiConsumer<ObjIntBox<CharSequence>, CharSequence> accumulator = (acc, t) -> {
1✔
1709
            if (acc.b == -1) {
1✔
1710
                acc.a = t;
1✔
1711
                acc.b = t.length();
1✔
1712
            } else if (acc.b > 0) {
1✔
1713
                int aLen = acc.a.length();
1✔
1714
                int bLen = t.length();
1✔
1715
                if (bLen < acc.b)
1✔
1716
                    acc.b = bLen;
1✔
1717
                for (int i = 0; i < acc.b; i++) {
1✔
1718
                    if (acc.a.charAt(aLen - 1 - i) != t.charAt(bLen - 1 - i)) {
1✔
1719
                        if (i > 0 && Character.isLowSurrogate(t.charAt(bLen - i)) && (Character.isHighSurrogate(t
1✔
1720
                                .charAt(bLen - 1 - i)) || Character.isHighSurrogate(acc.a.charAt(aLen - 1 - i))))
1✔
1721
                            i--;
1✔
1722
                        acc.b = i;
1✔
1723
                        break;
1✔
1724
                    }
1725
                }
1726
            }
1727
        };
1✔
1728
        return new CancellableCollectorImpl<>(() -> new ObjIntBox<>(null, -1), accumulator, (acc1, acc2) -> {
1✔
1729
            if (acc1.b == -1)
1✔
1730
                return acc2;
1✔
1731
            if (acc2.b != -1)
1✔
1732
                accumulator.accept(acc1, acc2.a.subSequence(acc2.a.length() - acc2.b, acc2.a.length()));
1✔
1733
            return acc1;
1✔
1734
        }, acc -> acc.a == null ? "" : acc.a.subSequence(acc.a.length() - acc.b, acc.a.length()).toString(),
1✔
1735
                acc -> acc.b == 0, UNORDERED_CHARACTERISTICS);
1✔
1736
    }
1737

1738
    /**
1739
     * Returns a collector which collects input elements into {@code List}
1740
     * removing the elements following their dominator element. The dominator
1741
     * elements are defined according to given isDominator {@code BiPredicate}.
1742
     * The isDominator relation must be transitive (if A dominates over B and B
1743
     * dominates over C, then A also dominates over C).
1744
     * 
1745
     * <p>
1746
     * This operation is similar to
1747
     * {@code streamEx.collapse(isDominator).toList()}. The important difference
1748
     * is that in this method {@code BiPredicate} accepts not the adjacent
1749
     * stream elements, but the leftmost element of the series (current
1750
     * dominator) and the current element.
1751
     * 
1752
     * <p>
1753
     * For example, consider the stream of numbers:
1754
     * 
1755
     * <pre>{@code
1756
     * StreamEx<Integer> stream = StreamEx.of(1, 5, 3, 4, 2, 7);
1757
     * }</pre>
1758
     * 
1759
     * <p>
1760
     * Using {@code stream.collapse((a, b) -> a >= b).toList()} you will get the
1761
     * numbers which are bigger than their immediate predecessor (
1762
     * {@code [1, 5, 4, 7]}), because (3, 4) pair is not collapsed. However
1763
     * using {@code stream.collect(dominators((a, b) -> a >= b))} you will get
1764
     * the numbers which are bigger than any predecessor ({@code [1, 5, 7]}) as
1765
     * 5 is the dominator element for the subsequent 3, 4 and 2.
1766
     * 
1767
     * @param <T> type of the input elements.
1768
     * @param isDominator a non-interfering, stateless, transitive
1769
     *        {@code BiPredicate} which returns true if the first argument is
1770
     *        the dominator for the second argument.
1771
     * @return a collector which collects input element into {@code List}
1772
     *         leaving only dominator elements.
1773
     * @throws NullPointerException if isDominator is null.
1774
     * @see StreamEx#collapse(BiPredicate)
1775
     * @since 0.5.1
1776
     */
1777
    public static <T> Collector<T, ?, List<T>> dominators(BiPredicate<? super T, ? super T> isDominator) {
1778
        Objects.requireNonNull(isDominator);
1✔
1779
        return Collector.of(ArrayList::new, (acc, t) -> {
1✔
1780
            if (acc.isEmpty() || !isDominator.test(acc.get(acc.size() - 1), t))
1✔
1781
                acc.add(t);
1✔
1782
        }, (acc1, acc2) -> {
1✔
1783
            if (acc1.isEmpty())
1✔
1784
                return acc2;
1✔
1785
            int i = 0, l = acc2.size();
1✔
1786
            T last = acc1.get(acc1.size() - 1);
1✔
1787
            while (i < l && isDominator.test(last, acc2.get(i)))
1✔
1788
                i++;
1✔
1789
            if (i < l)
1✔
1790
                acc1.addAll(acc2.subList(i, l));
1✔
1791
            return acc1;
1✔
1792
        });
1793
    }
1794

1795
    /**
1796
     * Returns a {@code Collector} which performs downstream reduction if all
1797
     * elements satisfy the {@code Predicate}. The result is described as an
1798
     * {@code Optional<R>}.
1799
     * 
1800
     * <p>
1801
     * The resulting collector returns an empty optional if at least one input
1802
     * element does not satisfy the predicate. Otherwise it returns an optional
1803
     * which contains the result of the downstream collector.
1804
     * 
1805
     * <p>
1806
     * This method returns a
1807
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1808
     * collector</a>: it may not process all the elements if some of items don't
1809
     * satisfy the predicate or if downstream collector is a short-circuiting
1810
     * collector.
1811
     * 
1812
     * <p>
1813
     * It's guaranteed that the downstream collector is not called for elements
1814
     * which don't satisfy the predicate.
1815
     *
1816
     * @param <T> the type of input elements
1817
     * @param <A> intermediate accumulation type of the downstream collector
1818
     * @param <R> result type of the downstream collector
1819
     * @param predicate a non-interfering, stateless predicate to checks whether
1820
     *        collector should proceed with element
1821
     * @param downstream a {@code Collector} implementing the downstream
1822
     *        reduction
1823
     * @return a {@code Collector} witch performs downstream reduction if all
1824
     *         elements satisfy the predicate
1825
     * @throws NullPointerException if mapper is null.
1826
     * @see Stream#allMatch(Predicate)
1827
     * @see AbstractStreamEx#dropWhile(Predicate)
1828
     * @see AbstractStreamEx#takeWhile(Predicate)
1829
     * @since 0.6.3
1830
     */
1831
    public static <T, A, R> Collector<T, ?, Optional<R>> ifAllMatch(Predicate<T> predicate,
1832
            Collector<T, A, R> downstream) {
1833
        Objects.requireNonNull(predicate);
1✔
1834
        Predicate<A> finished = finished(downstream);
1✔
1835
        Supplier<A> supplier = downstream.supplier();
1✔
1836
        BiConsumer<A, T> accumulator = downstream.accumulator();
1✔
1837
        BinaryOperator<A> combiner = downstream.combiner();
1✔
1838
        return new CancellableCollectorImpl<>(
1✔
1839
                () -> new PairBox<>(supplier.get(), Boolean.TRUE),
1✔
1840
                (acc, t) -> {
1841
                    if (acc.b && predicate.test(t)) {
1✔
1842
                        accumulator.accept(acc.a, t);
1✔
1843
                    } else {
1844
                        acc.b = Boolean.FALSE;
1✔
1845
                    }
1846
                },
1✔
1847
                (acc1, acc2) -> {
1848
                    if (acc1.b && acc2.b) {
1✔
1849
                        acc1.a = combiner.apply(acc1.a, acc2.a);
1✔
1850
                    } else {
1851
                        acc1.b = Boolean.FALSE;
1✔
1852
                    }
1853
                    return acc1;
1✔
1854
                },
1855
                acc -> acc.b ? Optional.of(downstream.finisher().apply(acc.a)) : Optional.empty(),
1✔
1856
                finished == null ? acc -> !acc.b : acc -> !acc.b || finished.test(acc.a),
1✔
1857
                downstream.characteristics().contains(Characteristics.UNORDERED) ? UNORDERED_CHARACTERISTICS
1✔
1858
                        : NO_CHARACTERISTICS);
1✔
1859
    }
1860

1861
    /**
1862
     * Returns a {@code Collector} which performs a possibly short-circuiting reduction of its
1863
     * input elements under a specified {@code BinaryOperator}. The result
1864
     * is described as an {@code Optional<T>}.
1865
     *
1866
     * <p>
1867
     * This collector behaves like {@link Collectors#reducing(BinaryOperator)}. However,
1868
     * it additionally accepts a zero element (also known as absorbing element). When zero element
1869
     * is passed to the accumulator then the result must be zero as well. So the collector
1870
     * takes the advantage of this and may short-circuit if zero is reached during the collection.
1871
     *
1872
     * <p>
1873
     * This method returns a
1874
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1875
     * collector</a>: it may not process all the elements if the result of reduction is equal to zero.
1876
     *
1877
     * <p>
1878
     * This collector is mostly useful as a downstream collector. To perform simple
1879
     * short-circuiting reduction, use {@link AbstractStreamEx#reduceWithZero(Object, BinaryOperator)}
1880
     * instead.
1881
     *
1882
     * @param zero zero element
1883
     * @param op an <a href="package-summary.html#Associativity">associative</a>
1884
     *        , <a href="package-summary.html#NonInterference">non-interfering
1885
     *        </a>, <a href="package-summary.html#Statelessness">stateless</a>
1886
     *        function to combine two elements into one.
1887
     * @param <T> the type of input elements
1888
     * @return a collector which returns an {@link Optional} describing the reduction result.
1889
     *         For empty stream an empty {@code Optional} is returned.
1890
     * @throws NullPointerException if op is null or the result of reduction is null
1891
     * @see #reducingWithZero(Object, Object, BinaryOperator)
1892
     * @see AbstractStreamEx#reduceWithZero(Object, BinaryOperator)
1893
     * @see Collectors#reducing(BinaryOperator)
1894
     * @since 0.7.3
1895
     */
1896
    public static <T> Collector<T, ?, Optional<T>> reducingWithZero(T zero, BinaryOperator<T> op) {
1897
        Objects.requireNonNull(op);
1✔
1898
        // acc.b: 0 = no element, 1 = has element, 2 = zero reached
1899
        return new CancellableCollectorImpl<>(
1✔
1900
            () -> new ObjIntBox<T>(null, 0),
1✔
1901
            (acc, t) -> {
1902
                if (acc.b != 2) {
1✔
1903
                    if (acc.b == 1) {
1✔
1904
                        t = op.apply(t, acc.a);
1✔
1905
                    }
1906
                    if (Objects.equals(t, zero)) {
1✔
1907
                        acc.b = 2;
1✔
1908
                        acc.a = zero;
1✔
1909
                    } else {
1910
                        acc.b = 1;
1✔
1911
                        acc.a = t;
1✔
1912
                    }
1913
                }
1914
            },
1✔
1915
            (acc1, acc2) -> {
1916
                if (acc1.b == 0 || acc2.b == 2) return acc2;
1✔
1917
                if (acc2.b == 0 || acc1.b == 2) return acc1;
1✔
1918
                T t = op.apply(acc1.a, acc2.a);
1✔
1919
                if (Objects.equals(t, zero)) {
1✔
1920
                    acc1.b = 2;
1✔
1921
                    acc1.a = zero;
1✔
1922
                } else {
1923
                    acc1.a = t;
1✔
1924
                }
1925
                return acc1;
1✔
1926
            },
1927
            acc -> acc.b == 0 ? Optional.empty() : Optional.of(acc.a),
1✔
1928
            acc -> acc.b == 2,
1✔
1929
            UNORDERED_CHARACTERISTICS
1930
        );
1931
    }
1932

1933
    /**
1934
     * Returns a {@code Collector} which performs a possibly short-circuiting reduction of its
1935
     * input elements using the provided identity value and a {@code BinaryOperator}.
1936
     *
1937
     * <p>
1938
     * This collector behaves like {@link Collectors#reducing(Object, BinaryOperator)}. However,
1939
     * it additionally accepts a zero element (also known as absorbing element). When zero element
1940
     * is passed to the accumulator then the result must be zero as well. So the collector
1941
     * takes the advantage of this and may short-circuit if zero is reached during the collection.
1942
     *
1943
     * <p>
1944
     * This method returns a
1945
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1946
     * collector</a>: it may not process all the elements if the result of reduction is equal to zero.
1947
     *
1948
     * <p>
1949
     * This collector is mostly useful as a downstream collector. To perform simple
1950
     * short-circuiting reduction, use {@link AbstractStreamEx#reduceWithZero(Object, BinaryOperator)}
1951
     * instead.
1952
     *
1953
     * @param zero zero element
1954
     * @param identity an identity element. For all {@code t}, {@code op.apply(t, identity)} is
1955
     *                 equal to {@code op.apply(identity, t)} and is equal to {@code t}.
1956
     * @param op an <a href="package-summary.html#Associativity">associative</a>
1957
     *        , <a href="package-summary.html#NonInterference">non-interfering
1958
     *        </a>, <a href="package-summary.html#Statelessness">stateless</a>
1959
     *        function to combine two elements into one.
1960
     * @param <T> the type of input elements
1961
     * @return a collector which returns the reduction result.
1962
     * @throws NullPointerException if op is null
1963
     * @see #reducingWithZero(Object, BinaryOperator) 
1964
     * @see AbstractStreamEx#reduceWithZero(Object, Object, BinaryOperator) 
1965
     * @see Collectors#reducing(Object, BinaryOperator) 
1966
     * @since 0.7.3
1967
     */
1968
    public static <T> Collector<T, ?, T> reducingWithZero(T zero, T identity, BinaryOperator<T> op) {
1969
        Objects.requireNonNull(op);
1✔
1970
        // acc.b: 1 = has element, 2 = zero reached
1971
        return new CancellableCollectorImpl<>(
1✔
1972
            () -> new ObjIntBox<>(identity, 1),
1✔
1973
            (acc, t) -> {
1974
                if (acc.b != 2) {
1✔
1975
                    t = op.apply(t, acc.a);
1✔
1976
                    if (Objects.equals(t, zero)) {
1✔
1977
                        acc.b = 2;
1✔
1978
                        acc.a = zero;
1✔
1979
                    } else {
1980
                        acc.b = 1;
1✔
1981
                        acc.a = t;
1✔
1982
                    }
1983
                }
1984
            },
1✔
1985
            (acc1, acc2) -> {
1986
                if (acc2.b == 2) return acc2;
1✔
1987
                if (acc1.b == 2) return acc1;
1✔
1988
                T t = op.apply(acc1.a, acc2.a);
1✔
1989
                if (Objects.equals(t, zero)) {
1✔
1990
                    acc1.b = 2;
1✔
1991
                    acc1.a = zero;
1✔
1992
                } else {
1993
                    acc1.a = t;
1✔
1994
                }
1995
                return acc1;
1✔
1996
            },
1997
            acc -> acc.a,
1✔
1998
            acc -> acc.b == 2,
1✔
1999
            UNORDERED_CHARACTERISTICS
2000
        );
2001
    }
2002
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc