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

amaembo / streamex / #677

02 Nov 2024 08:50AM UTC coverage: 99.673%. Remained the same
#677

push

amaembo
Optimize imports

5786 of 5805 relevant lines covered (99.67%)

1.0 hits per line

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

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

18
import java.util.*;
19
import java.util.Map.Entry;
20
import java.util.function.*;
21
import java.util.stream.Collector;
22
import java.util.stream.Collector.Characteristics;
23
import java.util.stream.Collectors;
24
import java.util.stream.Stream;
25

26
import static one.util.streamex.AbstractStreamEx.addToMap;
27
import static one.util.streamex.Internals.*;
28

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

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

59
    private static <T> Collector<T, ?, List<T>> empty() {
60
        return empty(ArrayList<T>::new);
1✔
61
    }
62

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

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

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

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

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

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

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

256
    /**
257
     * Returns a {@code Collector} which counts a number of distinct values the
258
     * mapper function returns for the stream elements.
259
     * 
260
     * <p>
261
     * The operation performed by the returned collector is equivalent to
262
     * {@code stream.map(mapper).distinct().count()}. This collector is mostly
263
     * useful as a downstream collector.
264
     * 
265
     * @param <T> the type of the input elements
266
     * @param mapper a function which classifies input elements.
267
     * @return a collector which counts a number of distinct classes the mapper
268
     *         function returns for the stream elements.
269
     * @throws NullPointerException if mapper is null.
270
     */
271
    public static <T> Collector<T, ?, Integer> distinctCount(Function<? super T, ?> mapper) {
272
        Objects.requireNonNull(mapper);
1✔
273
        return Collectors.collectingAndThen(Collectors.mapping(mapper, Collectors.toSet()), Set::size);
1✔
274
    }
275

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

310
    /**
311
     * Returns a {@code Collector} accepting elements of type {@code T} that
312
     * counts the number of input elements and returns result as {@code Integer}
313
     * . If no elements are present, the result is 0.
314
     *
315
     * @param <T> the type of the input elements
316
     * @return a {@code Collector} that counts the input elements
317
     * @since 0.3.3
318
     * @see Collectors#counting()
319
     */
320
    public static <T> Collector<T, ?, Integer> countingInt() {
321
        return PartialCollector.intSum().asRef((acc, t) -> acc[0]++);
1✔
322
    }
323

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

362
        Supplier<A1> c1Supplier = c1.supplier();
1✔
363
        Supplier<A2> c2Supplier = c2.supplier();
1✔
364
        BiConsumer<A1, ? super T> c1Accumulator = c1.accumulator();
1✔
365
        BiConsumer<A2, ? super T> c2Accumulator = c2.accumulator();
1✔
366
        BinaryOperator<A1> c1Combiner = c1.combiner();
1✔
367
        BinaryOperator<A2> c2combiner = c2.combiner();
1✔
368

369
        Supplier<PairBox<A1, A2>> supplier = () -> new PairBox<>(c1Supplier.get(), c2Supplier.get());
1✔
370
        BiConsumer<PairBox<A1, A2>, T> accumulator = (acc, v) -> {
1✔
371
            c1Accumulator.accept(acc.a, v);
1✔
372
            c2Accumulator.accept(acc.b, v);
1✔
373
        };
1✔
374
        BinaryOperator<PairBox<A1, A2>> combiner = (acc1, acc2) -> {
1✔
375
            acc1.a = c1Combiner.apply(acc1.a, acc2.a);
1✔
376
            acc1.b = c2combiner.apply(acc1.b, acc2.b);
1✔
377
            return acc1;
1✔
378
        };
379
        Function<PairBox<A1, A2>, R> resFinisher = acc -> {
1✔
380
            R1 r1 = c1.finisher().apply(acc.a);
1✔
381
            R2 r2 = c2.finisher().apply(acc.b);
1✔
382
            return finisher.apply(r1, r2);
1✔
383
        };
384
        Predicate<A1> c1Finished = finished(c1);
1✔
385
        Predicate<A2> c2Finished = finished(c2);
1✔
386
        if (c1Finished != null && c2Finished != null) {
1✔
387
            Predicate<PairBox<A1, A2>> finished = acc -> c1Finished.test(acc.a) && c2Finished.test(acc.b);
1✔
388
            return new CancellableCollectorImpl<>(supplier, accumulator, combiner, resFinisher, finished, c);
1✔
389
        }
390
        return Collector.of(supplier, accumulator, combiner, resFinisher, c.toArray(new Characteristics[0]));
1✔
391
    }
392

393
    /**
394
     * Returns a {@code Collector} which finds the minimal and maximal element
395
     * according to the supplied comparator, then applies finisher function to
396
     * them producing the final result.
397
     * 
398
     * <p>
399
     * This collector produces stable result for ordered stream: if several
400
     * minimal or maximal elements appear, the collector always selects the
401
     * first encountered.
402
     * 
403
     * <p>
404
     * If there are no input elements, the finisher method is not called and
405
     * empty {@code Optional} is returned. Otherwise the finisher result is
406
     * wrapped into {@code Optional}.
407
     *
408
     * @param <T> the type of the input elements
409
     * @param <R> the type of the result wrapped into {@code Optional}
410
     * @param comparator comparator which is used to find minimal and maximal
411
     *        element
412
     * @param finisher a {@link BiFunction} which takes minimal and maximal
413
     *        element and produces the final result.
414
     * @return a {@code Collector} which finds minimal and maximal elements.
415
     * @throws NullPointerException if comparator is null, finisher is null,
416
     * or finisher returns null.
417
     */
418
    public static <T, R> Collector<T, ?, Optional<R>> minMax(Comparator<? super T> comparator,
419
            BiFunction<? super T, ? super T, ? extends R> finisher) {
420
        Objects.requireNonNull(finisher);
1✔
421
        return pairing(Collectors.minBy(comparator), Collectors.maxBy(comparator),
1✔
422
            (min, max) -> min.isPresent() ? Optional.of(finisher.apply(min.get(), max.get())) : Optional.empty());
1✔
423
    }
424

425
    /**
426
     * Returns a {@code Collector} which finds all the elements which are equal
427
     * to each other and bigger than any other element according to the
428
     * specified {@link Comparator}. The found elements are reduced using the
429
     * specified downstream {@code Collector}.
430
     *
431
     * @param <T> the type of the input elements
432
     * @param <A> the intermediate accumulation type of the downstream collector
433
     * @param <D> the result type of the downstream reduction
434
     * @param comparator a {@code Comparator} to compare the elements
435
     * @param downstream a {@code Collector} implementing the downstream
436
     *        reduction
437
     * @return a {@code Collector} which finds all the maximal elements.
438
     * @throws NullPointerException if comparator is null, or downstream is null.
439
     * @see #maxAll(Comparator)
440
     * @see #maxAll(Collector)
441
     * @see #maxAll()
442
     */
443
    public static <T, A, D> Collector<T, ?, D> maxAll(Comparator<? super T> comparator,
444
            Collector<? super T, A, D> downstream) {
445
        Objects.requireNonNull(comparator);
1✔
446
        Supplier<A> downstreamSupplier = downstream.supplier();
1✔
447
        BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
1✔
448
        BinaryOperator<A> downstreamCombiner = downstream.combiner();
1✔
449
        Supplier<PairBox<A, T>> supplier = () -> new PairBox<>(downstreamSupplier.get(), none());
1✔
450
        BiConsumer<PairBox<A, T>, T> accumulator = (acc, t) -> {
1✔
451
            if (acc.b == NONE) {
1✔
452
                downstreamAccumulator.accept(acc.a, t);
1✔
453
                acc.b = t;
1✔
454
            } else {
455
                int cmp = comparator.compare(t, acc.b);
1✔
456
                if (cmp > 0) {
1✔
457
                    acc.a = downstreamSupplier.get();
1✔
458
                    acc.b = t;
1✔
459
                }
460
                if (cmp >= 0)
1✔
461
                    downstreamAccumulator.accept(acc.a, t);
1✔
462
            }
463
        };
1✔
464
        BinaryOperator<PairBox<A, T>> combiner = (acc1, acc2) -> {
1✔
465
            if (acc2.b == NONE) {
1✔
466
                return acc1;
1✔
467
            }
468
            if (acc1.b == NONE) {
1✔
469
                return acc2;
1✔
470
            }
471
            int cmp = comparator.compare(acc1.b, acc2.b);
1✔
472
            if (cmp > 0) {
1✔
473
                return acc1;
1✔
474
            }
475
            if (cmp < 0) {
1✔
476
                return acc2;
1✔
477
            }
478
            acc1.a = downstreamCombiner.apply(acc1.a, acc2.a);
1✔
479
            return acc1;
1✔
480
        };
481
        Function<PairBox<A, T>, D> finisher = acc -> downstream.finisher().apply(acc.a);
1✔
482
        return Collector.of(supplier, accumulator, combiner, finisher);
1✔
483
    }
484

485
    /**
486
     * Returns a {@code Collector} which finds all the elements which are equal
487
     * to each other and bigger than any other element according to the
488
     * specified {@link Comparator}. The found elements are collected to
489
     * {@link List}.
490
     *
491
     * @param <T> the type of the input elements
492
     * @param comparator a {@code Comparator} to compare the elements
493
     * @return a {@code Collector} which finds all the maximal elements and
494
     *         collects them to the {@code List}.
495
     * @throws NullPointerException if comparator is null.
496
     * @see #maxAll(Comparator, Collector)
497
     * @see #maxAll()
498
     */
499
    public static <T> Collector<T, ?, List<T>> maxAll(Comparator<? super T> comparator) {
500
        return maxAll(comparator, Collectors.toList());
1✔
501
    }
502

503
    /**
504
     * Returns a {@code Collector} which finds all the elements which are equal
505
     * to each other and bigger than any other element according to the natural
506
     * order. The found elements are reduced using the specified downstream
507
     * {@code Collector}.
508
     *
509
     * @param <T> the type of the input elements
510
     * @param <A> the intermediate accumulation type of the downstream collector
511
     * @param <D> the result type of the downstream reduction
512
     * @param downstream a {@code Collector} implementing the downstream
513
     *        reduction
514
     * @return a {@code Collector} which finds all the maximal elements.
515
     * @throws NullPointerException if downstream is null.
516
     * @see #maxAll(Comparator, Collector)
517
     * @see #maxAll(Comparator)
518
     * @see #maxAll()
519
     */
520
    public static <T extends Comparable<? super T>, A, D> Collector<T, ?, D> maxAll(Collector<T, A, D> downstream) {
521
        return maxAll(Comparator.<T>naturalOrder(), downstream);
1✔
522
    }
523

524
    /**
525
     * Returns a {@code Collector} which finds all the elements which are equal
526
     * to each other and bigger than any other element according to the natural
527
     * order. The found elements are collected to {@link List}.
528
     *
529
     * @param <T> the type of the input elements
530
     * @return a {@code Collector} which finds all the maximal elements and
531
     *         collects them to the {@code List}.
532
     * @see #maxAll(Comparator)
533
     * @see #maxAll(Collector)
534
     */
535
    public static <T extends Comparable<? super T>> Collector<T, ?, List<T>> maxAll() {
536
        return maxAll(Comparator.<T>naturalOrder(), Collectors.toList());
1✔
537
    }
538

539
    /**
540
     * Returns a {@code Collector} which finds all the elements which are equal
541
     * to each other and smaller than any other element according to the
542
     * specified {@link Comparator}. The found elements are reduced using the
543
     * specified downstream {@code Collector}.
544
     *
545
     * @param <T> the type of the input elements
546
     * @param <A> the intermediate accumulation type of the downstream collector
547
     * @param <D> the result type of the downstream reduction
548
     * @param comparator a {@code Comparator} to compare the elements
549
     * @param downstream a {@code Collector} implementing the downstream
550
     *        reduction
551
     * @return a {@code Collector} which finds all the minimal elements.
552
     * @throws NullPointerException if comparator is null, or downstream is null.
553
     * @see #minAll(Comparator)
554
     * @see #minAll(Collector)
555
     * @see #minAll()
556
     */
557
    public static <T, A, D> Collector<T, ?, D> minAll(Comparator<? super T> comparator, Collector<T, A, D> downstream) {
558
        return maxAll(comparator.reversed(), downstream);
1✔
559
    }
560

561
    /**
562
     * Returns a {@code Collector} which finds all the elements which are equal
563
     * to each other and smaller than any other element according to the
564
     * specified {@link Comparator}. The found elements are collected to
565
     * {@link List}.
566
     *
567
     * @param <T> the type of the input elements
568
     * @param comparator a {@code Comparator} to compare the elements
569
     * @return a {@code Collector} which finds all the minimal elements and
570
     *         collects them to the {@code List}.
571
     * @throws NullPointerException if comparator is null.
572
     * @see #minAll(Comparator, Collector)
573
     * @see #minAll()
574
     */
575
    public static <T> Collector<T, ?, List<T>> minAll(Comparator<? super T> comparator) {
576
        return maxAll(comparator.reversed(), Collectors.toList());
1✔
577
    }
578

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

600
    /**
601
     * Returns a {@code Collector} which finds all the elements which are equal
602
     * to each other and smaller than any other element according to the natural
603
     * order. The found elements are collected to {@link List}.
604
     *
605
     * @param <T> the type of the input elements
606
     * @return a {@code Collector} which finds all the minimal elements and
607
     *         collects them to the {@code List}.
608
     * @see #minAll(Comparator)
609
     * @see #minAll(Collector)
610
     */
611
    public static <T extends Comparable<? super T>> Collector<T, ?, List<T>> minAll() {
612
        return maxAll(Comparator.<T>reverseOrder(), Collectors.toList());
1✔
613
    }
614

615
    /**
616
     * Returns a {@code Collector} which collects the stream element if stream
617
     * contains exactly one element.
618
     * 
619
     * <p>
620
     * This method returns a
621
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
622
     * collector</a>.
623
     * 
624
     * @param <T> the type of the input elements
625
     * @return a collector which returns an {@link Optional} describing the only
626
     *         element of the stream. For empty stream or stream containing more
627
     *         than one element an empty {@code Optional} is returned.
628
     * @throws NullPointerException if the only stream element is null.
629
     * @since 0.4.0
630
     */
631
    public static <T> Collector<T, ?, Optional<T>> onlyOne() {
632
        return new CancellableCollectorImpl<T, Box<Optional<T>>, Optional<T>>(Box::new, (box,
1✔
633
                t) -> box.a = box.a == null ? Optional.of(t) : Optional.empty(), (box1, box2) -> box1.a == null ? box2
1✔
634
                        : box2.a == null ? box1 : new Box<>(Optional.empty()), box -> box.a == null ? Optional.empty()
1✔
635
                                : box.a, box -> box.a != null && !box.a.isPresent(), UNORDERED_CHARACTERISTICS);
1✔
636
    }
637

638
    /**
639
     * Returns a {@code Collector} which collects the stream element satisfying the predicate
640
     * if there is only one such element.
641
     *
642
     * <p>
643
     * This method returns a
644
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
645
     * collector</a>.
646
     *
647
     * @param predicate a predicate to be applied to the stream elements
648
     * @param <T> the type of the input elements
649
     * @return a collector which returns an {@link Optional} describing the only
650
     *         element of the stream satisfying the predicate. If stream contains no elements satisfying the predicate,
651
     *         or more than one such element, an empty {@code Optional} is returned.
652
     * @throws NullPointerException if predicate is null or the only stream element is null.
653
     * @since 0.6.7
654
     */
655
    public static <T> Collector<T, ?, Optional<T>> onlyOne(Predicate<? super T> predicate) {
656
        return filtering(predicate, onlyOne());
1✔
657
    }
658

659
    /**
660
     * Returns a {@code Collector} which collects only the first stream element
661
     * if any.
662
     * 
663
     * <p>
664
     * This method returns a
665
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
666
     * collector</a>.
667
     * 
668
     * <p>
669
     * The operation performed by the returned collector is equivalent to
670
     * {@code stream.findFirst()}. This collector is mostly useful as a
671
     * downstream collector.
672
     * 
673
     * @param <T> the type of the input elements
674
     * @return a collector which returns an {@link Optional} which describes the
675
     *         first element of the stream. For empty stream an empty
676
     *         {@code Optional} is returned.
677
     * @throws NullPointerException if the first stream element is null.
678
     */
679
    public static <T> Collector<T, ?, Optional<T>> first() {
680
        return new CancellableCollectorImpl<>(() -> new Box<T>(none()), (box, t) -> {
1✔
681
            if (box.a == NONE)
1✔
682
                box.a = t;
1✔
683
        }, (box1, box2) -> box1.a == NONE ? box2 : box1, box -> box.a == NONE ? Optional.empty() : Optional.of(box.a),
1✔
684
                box -> box.a != NONE, NO_CHARACTERISTICS);
1✔
685
    }
686

687
    /**
688
     * Returns a {@code Collector} which collects only the last stream element
689
     * if any.
690
     * 
691
     * @param <T> the type of the input elements
692
     * @return a collector which returns an {@link Optional} which describes the
693
     *         last element of the stream. For empty stream an empty
694
     *         {@code Optional} is returned.
695
     * @throws NullPointerException if the last stream element is null.
696
     */
697
    public static <T> Collector<T, ?, Optional<T>> last() {
698
        return Collector.of(() -> new Box<T>(none()), (box, t) -> box.a = t,
1✔
699
            (box1, box2) -> box2.a == NONE ? box1 : box2, box -> box.a == NONE ? Optional.empty() : Optional.of(box.a));
1✔
700
    }
701

702
    /**
703
     * Returns a {@code Collector} which collects at most specified number of
704
     * the first stream elements into the {@link List}.
705
     *
706
     * <p>
707
     * This method returns a
708
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
709
     * collector</a>.
710
     * 
711
     * <p>
712
     * There are no guarantees on the type, mutability, serializability, or
713
     * thread-safety of the {@code List} returned.
714
     * 
715
     * <p>
716
     * The operation performed by the returned collector is equivalent to
717
     * {@code stream.limit(n).collect(Collectors.toList())}. This collector is
718
     * mostly useful as a downstream collector.
719
     * 
720
     * @param <T> the type of the input elements
721
     * @param n maximum number of stream elements to preserve
722
     * @return a collector which returns a {@code List} containing the first n
723
     *         stream elements or less if the stream was shorter.
724
     */
725
    public static <T> Collector<T, ?, List<T>> head(int n) {
726
        if (n <= 0)
1✔
727
            return empty();
1✔
728
        return new CancellableCollectorImpl<>(ArrayList::new, (acc, t) -> {
1✔
729
            if (acc.size() < n)
1✔
730
                acc.add(t);
1✔
731
        }, (acc1, acc2) -> {
1✔
732
            acc1.addAll(acc2.subList(0, Math.min(acc2.size(), n - acc1.size())));
1✔
733
            return acc1;
1✔
734
        }, Function.identity(), acc -> acc.size() >= n, ID_CHARACTERISTICS);
1✔
735
    }
736

737
    /**
738
     * Returns a {@code Collector} which collects at most specified number of
739
     * the last stream elements into the {@link List}.
740
     * 
741
     * <p>
742
     * There are no guarantees on the type, mutability, serializability, or
743
     * thread-safety of the {@code List} returned.
744
     * 
745
     * <p>
746
     * When supplied {@code n} is less or equal to zero, this method returns a
747
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
748
     * collector</a> which ignores the input and produces an empty list.
749
     * 
750
     * @param <T> the type of the input elements
751
     * @param n maximum number of stream elements to preserve
752
     * @return a collector which returns a {@code List} containing the last n
753
     *         stream elements or less if the stream was shorter.
754
     */
755
    public static <T> Collector<T, ?, List<T>> tail(int n) {
756
        if (n <= 0)
1✔
757
            return empty();
1✔
758
        return Collector.<T, Deque<T>, List<T>>of(ArrayDeque::new, (acc, t) -> {
1✔
759
            if (acc.size() == n)
1✔
760
                acc.pollFirst();
1✔
761
            acc.addLast(t);
1✔
762
        }, (acc1, acc2) -> {
1✔
763
            while (acc2.size() < n && !acc1.isEmpty()) {
1✔
764
                acc2.addFirst(acc1.pollLast());
1✔
765
            }
766
            return acc2;
1✔
767
        }, ArrayList::new);
768
    }
769

770
    /**
771
     * Returns a {@code Collector} which collects at most specified number of
772
     * the greatest stream elements according to the specified
773
     * {@link Comparator} into the {@link List}. The resulting {@code List} is
774
     * sorted in comparator reverse order (greatest element is the first). The
775
     * order of equal elements is the same as in the input stream.
776
     * 
777
     * <p>
778
     * The operation performed by the returned collector is equivalent to
779
     * {@code stream.sorted(comparator.reversed()).limit(n).collect(Collectors.toList())}
780
     * , but usually performed much faster if {@code n} is much less than the
781
     * stream size.
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 comparator the comparator to compare the elements by
794
     * @param n maximum number of stream elements to preserve
795
     * @return a collector which returns a {@code List} containing the greatest
796
     *         n stream elements or less if the stream was shorter.
797
     * @throws NullPointerException if comparator is null.
798
     */
799
    public static <T> Collector<T, ?, List<T>> greatest(Comparator<? super T> comparator, int n) {
800
        return least(comparator.reversed(), n);
1✔
801
    }
802

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

834
    /**
835
     * Returns a {@code Collector} which collects at most specified number of
836
     * the least stream elements according to the specified {@link Comparator}
837
     * into the {@link List}. The resulting {@code List} is sorted in comparator
838
     * order (least element is the first). The order of equal elements is the
839
     * same as in the input stream.
840
     * 
841
     * <p>
842
     * The operation performed by the returned collector is equivalent to
843
     * {@code stream.sorted(comparator).limit(n).collect(Collectors.toList())},
844
     * but usually performed much faster if {@code n} is much less than the
845
     * stream size.
846
     * 
847
     * <p>
848
     * There are no guarantees on the type, mutability, serializability, or
849
     * thread-safety of the {@code List} returned.
850
     * 
851
     * <p>
852
     * When supplied {@code n} is less or equal to zero, this method returns a
853
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
854
     * collector</a> which ignores the input and produces an empty list.
855
     * 
856
     * @param <T> the type of the input elements
857
     * @param comparator the comparator to compare the elements by
858
     * @param n maximum number of stream elements to preserve
859
     * @return a collector which returns a {@code List} containing the least n
860
     *         stream elements or less if the stream was shorter.
861
     * @throws NullPointerException if comparator is null.
862
     */
863
    public static <T> Collector<T, ?, List<T>> least(Comparator<? super T> comparator, int n) {
864
        Objects.requireNonNull(comparator);
1✔
865
        if (n <= 0)
1✔
866
            return empty();
1✔
867
        if (n == 1) {
1✔
868
            return Collector.of(() -> new Box<T>(none()), (box, t) -> {
1✔
869
                if (box.a == NONE || comparator.compare(t, box.a) < 0)
1✔
870
                    box.a = t;
1✔
871
            }, (box1, box2) -> (box2.a != NONE && (box1.a == NONE || comparator.compare(box2.a, box1.a) < 0)) ? box2
1✔
872
                    : box1, box -> box.a == NONE ? new ArrayList<>() : new ArrayList<>(Collections.singleton(box.a)));
1✔
873
        }
874
        if (n >= Integer.MAX_VALUE / 2)
1✔
875
            return collectingAndThen(Collectors.toList(), list -> {
1✔
876
                list.sort(comparator);
1✔
877
                if (list.size() <= n)
1✔
878
                    return list;
1✔
879
                return new ArrayList<>(list.subList(0, n));
×
880
            });
881
        return Collector.<T, Limiter<T>, List<T>>of(() -> new Limiter<>(n, comparator), Limiter::put, Limiter::putAll,
1✔
882
            pq -> {
883
                pq.sort();
1✔
884
                return new ArrayList<>(pq);
1✔
885
            });
886
    }
887

888
    /**
889
     * Returns a {@code Collector} which collects at most specified number of
890
     * the least stream elements according to the natural order into the
891
     * {@link List}. The resulting {@code List} is sorted in natural order
892
     * (least element is the first). The order of equal elements is the same as
893
     * in the input stream.
894
     * 
895
     * <p>
896
     * The operation performed by the returned collector is equivalent to
897
     * {@code stream.sorted().limit(n).collect(Collectors.toList())}, but
898
     * usually performed much faster if {@code n} is much less than the stream
899
     * size.
900
     * 
901
     * <p>
902
     * There are no guarantees on the type, mutability, serializability, or
903
     * thread-safety of the {@code List} returned.
904
     * 
905
     * <p>
906
     * When supplied {@code n} is less or equal to zero, this method returns a
907
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
908
     * collector</a> which ignores the input and produces an empty list.
909
     * 
910
     * @param <T> the type of the input elements
911
     * @param n maximum number of stream elements to preserve
912
     * @return a collector which returns a {@code List} containing the least n
913
     *         stream elements or less if the stream was shorter.
914
     */
915
    public static <T extends Comparable<? super T>> Collector<T, ?, List<T>> least(int n) {
916
        return least(Comparator.<T>naturalOrder(), n);
1✔
917
    }
918

919
    /**
920
     * Returns a {@code Collector} which finds the index of the minimal stream
921
     * element according to the specified {@link Comparator}. If there are
922
     * several minimal elements, the index of the first one is returned.
923
     *
924
     * @param <T> the type of the input elements
925
     * @param comparator a {@code Comparator} to compare the elements
926
     * @return a {@code Collector} which finds the index of the minimal element.
927
     * @throws NullPointerException if comparator is null.
928
     * @see #minIndex()
929
     * @since 0.3.5
930
     */
931
    public static <T> Collector<T, ?, OptionalLong> minIndex(Comparator<? super T> comparator) {
932
        Objects.requireNonNull(comparator);
1✔
933
        class Container {
1✔
934
            T value;
935
            long count = 0;
1✔
936
            long index = -1;
1✔
937
        }
938

939
        return Collector.of(Container::new, (c, t) -> {
1✔
940
            if (c.index == -1 || comparator.compare(c.value, t) > 0) {
1✔
941
                c.value = t;
1✔
942
                c.index = c.count;
1✔
943
            }
944
            c.count++;
1✔
945
        }, (c1, c2) -> {
1✔
946
            if (c1.index == -1 || (c2.index != -1 && comparator.compare(c1.value, c2.value) > 0)) {
1✔
947
                c2.index += c1.count;
1✔
948
                c2.count += c1.count;
1✔
949
                return c2;
1✔
950
            }
951
            c1.count += c2.count;
1✔
952
            return c1;
1✔
953
        }, c -> c.index == -1 ? OptionalLong.empty() : OptionalLong.of(c.index));
1✔
954
    }
955

956
    /**
957
     * Returns a {@code Collector} which finds the index of the minimal stream
958
     * element according to the elements natural order. If there are several
959
     * minimal elements, the index of the first one is returned.
960
     *
961
     * @param <T> the type of the input elements
962
     * @return a {@code Collector} which finds the index of the minimal element.
963
     * @see #minIndex(Comparator)
964
     * @since 0.3.5
965
     */
966
    public static <T extends Comparable<? super T>> Collector<T, ?, OptionalLong> minIndex() {
967
        return minIndex(Comparator.naturalOrder());
1✔
968
    }
969

970
    /**
971
     * Returns a {@code Collector} which finds the index of the maximal stream
972
     * element according to the specified {@link Comparator}. If there are
973
     * several maximal elements, the index of the first one is returned.
974
     *
975
     * @param <T> the type of the input elements
976
     * @param comparator a {@code Comparator} to compare the elements
977
     * @return a {@code Collector} which finds the index of the maximal element.
978
     * @throws NullPointerException if comparator is null.
979
     * @see #maxIndex()
980
     * @since 0.3.5
981
     */
982
    public static <T> Collector<T, ?, OptionalLong> maxIndex(Comparator<? super T> comparator) {
983
        return minIndex(comparator.reversed());
1✔
984
    }
985

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

1000
    /**
1001
     * Returns a {@code Collector} implementing a cascaded "group by" operation
1002
     * on input elements of type {@code T}, for classification function which
1003
     * maps input elements to the enum values. The downstream reduction for
1004
     * repeating keys is performed using the specified downstream
1005
     * {@code Collector}.
1006
     *
1007
     * <p>
1008
     * Unlike the {@link Collectors#groupingBy(Function, Collector)} collector
1009
     * this collector produces an {@link EnumMap} which contains all possible
1010
     * keys including keys which were never returned by the classification
1011
     * function. These keys are mapped to the default collector value which is
1012
     * equivalent to collecting an empty stream with the same collector.
1013
     * 
1014
     * <p>
1015
     * This method returns a
1016
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1017
     * collector</a> if the downstream collector is short-circuiting. The
1018
     * collection might stop when for every possible enum key the downstream
1019
     * collection is known to be finished.
1020
     *
1021
     * @param <T> the type of the input elements
1022
     * @param <K> the type of the enum values returned by the classifier
1023
     * @param <A> the intermediate accumulation type of the downstream collector
1024
     * @param <D> the result type of the downstream reduction
1025
     * @param enumClass the class of enum values returned by the classifier
1026
     * @param classifier a classifier function mapping input elements to enum
1027
     *        values
1028
     * @param downstream a {@code Collector} implementing the downstream
1029
     *        reduction
1030
     * @return a {@code Collector} implementing the cascaded group-by operation
1031
     * @throws NullPointerException if enumClass is null, classifier is null, or downstream is null.
1032
     * @see Collectors#groupingBy(Function, Collector)
1033
     * @see #groupingBy(Function, Set, Supplier, Collector)
1034
     * @since 0.3.7
1035
     */
1036
    public static <T, K extends Enum<K>, A, D> Collector<T, ?, EnumMap<K, D>> groupingByEnum(Class<K> enumClass,
1037
            Function<? super T, K> classifier, Collector<? super T, A, D> downstream) {
1038
        return groupingBy(classifier, EnumSet.allOf(enumClass), () -> new EnumMap<>(enumClass), downstream);
1✔
1039
    }
1040

1041
    /**
1042
     * Returns a {@code Collector} implementing a cascaded "group by" operation
1043
     * on input elements of type {@code T}, grouping elements according to a
1044
     * classification function, and then performing a reduction operation on the
1045
     * values associated with a given key using the specified downstream
1046
     * {@code Collector}.
1047
     *
1048
     * <p>
1049
     * There are no guarantees on the type, mutability, serializability, or
1050
     * thread-safety of the {@code Map} returned.
1051
     *
1052
     * <p>
1053
     * The main difference of this collector from
1054
     * {@link Collectors#groupingBy(Function, Collector)} is that it accepts
1055
     * additional domain parameter which is the {@code Set} of all possible map
1056
     * keys. If the mapper function produces the key out of domain, an
1057
     * {@code IllegalStateException} will occur. If the mapper function does not
1058
     * produce some of domain keys at all, they are also added to the result.
1059
     * These keys are mapped to the default collector value which is equivalent
1060
     * to collecting an empty stream with the same collector.
1061
     * 
1062
     * <p>
1063
     * This method returns a
1064
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1065
     * collector</a> if the downstream collector is short-circuiting. The
1066
     * collection might stop when for every possible key from the domain the
1067
     * downstream collection is known to be finished.
1068
     *
1069
     * @param <T> the type of the input elements
1070
     * @param <K> the type of the keys
1071
     * @param <A> the intermediate accumulation type of the downstream collector
1072
     * @param <D> the result type of the downstream reduction
1073
     * @param classifier a classifier function mapping input elements to keys
1074
     * @param domain a domain of all possible key values
1075
     * @param downstream a {@code Collector} implementing the downstream
1076
     *        reduction
1077
     * @return a {@code Collector} implementing the cascaded group-by operation
1078
     *         with given domain
1079
     * @throws NullPointerException if classifier is null, domain is null, or downstream is null.
1080
     *
1081
     * @see #groupingBy(Function, Set, Supplier, Collector)
1082
     * @see #groupingByEnum(Class, Function, Collector)
1083
     * @since 0.4.0
1084
     */
1085
    public static <T, K, D, A> Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,
1086
            Set<K> domain, Collector<? super T, A, D> downstream) {
1087
        return groupingBy(classifier, domain, HashMap::new, downstream);
1✔
1088
    }
1089

1090
    /**
1091
     * Returns a {@code Collector} implementing a cascaded "group by" operation
1092
     * on input elements of type {@code T}, grouping elements according to a
1093
     * classification function, and then performing a reduction operation on the
1094
     * values associated with a given key using the specified downstream
1095
     * {@code Collector}. The {@code Map} produced by the Collector is created
1096
     * with the supplied factory function.
1097
     *
1098
     * <p>
1099
     * The main difference of this collector from
1100
     * {@link Collectors#groupingBy(Function, Supplier, Collector)} is that it
1101
     * accepts additional domain parameter which is the {@code Set} of all
1102
     * possible map keys. If the mapper function produces the key out of domain,
1103
     * an {@code IllegalStateException} will occur. If the mapper function does
1104
     * not produce some of domain keys at all, they are also added to the
1105
     * result. These keys are mapped to the default collector value which is
1106
     * equivalent to collecting an empty stream with the same collector.
1107
     * 
1108
     * <p>
1109
     * This method returns a
1110
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1111
     * collector</a> if the downstream collector is short-circuiting. The
1112
     * collection might stop when for every possible key from the domain the
1113
     * downstream collection is known to be finished.
1114
     *
1115
     * @param <T> the type of the input elements
1116
     * @param <K> the type of the keys
1117
     * @param <A> the intermediate accumulation type of the downstream collector
1118
     * @param <D> the result type of the downstream reduction
1119
     * @param <M> the type of the resulting {@code Map}
1120
     * @param classifier a classifier function mapping input elements to keys
1121
     * @param domain a domain of all possible key values
1122
     * @param downstream a {@code Collector} implementing the downstream
1123
     *        reduction
1124
     * @param mapFactory a function which, when called, produces a new empty
1125
     *        {@code Map} of the desired type
1126
     * @return a {@code Collector} implementing the cascaded group-by operation
1127
     *         with given domain
1128
     * @throws NullPointerException if classifier is null, domain is null, mapFactory is null, or downstream is null.
1129
     *
1130
     * @see #groupingBy(Function, Set, Collector)
1131
     * @see #groupingByEnum(Class, Function, Collector)
1132
     * @since 0.4.0
1133
     */
1134
    public static <T, K, D, A, M extends Map<K, D>> Collector<T, ?, M> groupingBy(
1135
            Function<? super T, ? extends K> classifier, Set<K> domain, Supplier<M> mapFactory,
1136
            Collector<? super T, A, D> downstream) {
1137
        Objects.requireNonNull(classifier);
1✔
1138
        Objects.requireNonNull(domain);
1✔
1139
        Objects.requireNonNull(mapFactory);
1✔
1140
        Supplier<A> downstreamSupplier = downstream.supplier();
1✔
1141
        Collector<T, ?, M> groupingBy;
1142
        Function<K, A> supplier = k -> {
1✔
1143
            if (!domain.contains(k))
1✔
1144
                throw new IllegalStateException("Classifier returned value '" + k + "' which is out of domain");
1✔
1145
            return downstreamSupplier.get();
1✔
1146
        };
1147
        BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
1✔
1148
        BiConsumer<Map<K, A>, T> accumulator = (m, t) -> {
1✔
1149
            K key = Objects.requireNonNull(classifier.apply(t));
1✔
1150
            A container = m.computeIfAbsent(key, supplier);
1✔
1151
            downstreamAccumulator.accept(container, t);
1✔
1152
        };
1✔
1153
        PartialCollector<Map<K, A>, M> partial = PartialCollector.grouping(mapFactory, downstream);
1✔
1154
        Predicate<A> downstreamFinished = finished(downstream);
1✔
1155
        if (downstreamFinished != null) {
1✔
1156
            int size = domain.size();
1✔
1157
            groupingBy = partial.asCancellable(accumulator, map -> {
1✔
1158
                if (map.size() < size)
1✔
1159
                    return false;
1✔
1160
                for (A container : map.values()) {
1✔
1161
                    if (!downstreamFinished.test(container))
1✔
1162
                        return false;
1✔
1163
                }
1✔
1164
                return true;
1✔
1165
            });
1166
        } else {
1✔
1167
            groupingBy = partial.asRef(accumulator);
1✔
1168
        }
1169
        return collectingAndThen(groupingBy, map -> {
1✔
1170
            Function<A, D> finisher = downstream.finisher();
1✔
1171
            domain.forEach(key -> map.computeIfAbsent(key, k -> finisher.apply(downstreamSupplier.get())));
1✔
1172
            return map;
1✔
1173
        });
1174
    }
1175

1176
    /**
1177
     * Returns a {@code Collector} which collects the intersection of the input
1178
     * collections into the newly-created {@link Set}.
1179
     *
1180
     * <p>
1181
     * The returned collector produces an empty set if the input is empty or
1182
     * intersection of the input collections is empty.
1183
     * 
1184
     * <p>
1185
     * There are no guarantees on the type, mutability, serializability, or
1186
     * thread-safety of the {@code Set} returned.
1187
     *
1188
     * <p>
1189
     * This method returns a
1190
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1191
     * collector</a>: it may not process all the elements if the resulting
1192
     * intersection is empty.
1193
     * 
1194
     * @param <T> the type of the elements in the input collections
1195
     * @param <S> the type of the input collections
1196
     * @return a {@code Collector} which finds all the minimal elements and
1197
     *         collects them to the {@code List}.
1198
     * @since 0.4.0
1199
     */
1200
    public static <T, S extends Collection<T>> Collector<S, ?, Set<T>> intersecting() {
1201
        return new CancellableCollectorImpl<S, Box<Set<T>>, Set<T>>(Box::new, (b, t) -> {
1✔
1202
            if (b.a == null) {
1✔
1203
                b.a = new HashSet<>(t);
1✔
1204
            } else {
1205
                b.a.retainAll(t);
1✔
1206
            }
1207
        }, (b1, b2) -> {
1✔
1208
            if (b1.a == null)
1✔
1209
                return b2;
1✔
1210
            if (b2.a != null)
1✔
1211
                b1.a.retainAll(b2.a);
1✔
1212
            return b1;
1✔
1213
        }, b -> b.a == null ? Collections.emptySet() : b.a, b -> b.a != null && b.a.isEmpty(),
1✔
1214
                UNORDERED_CHARACTERISTICS);
1215
    }
1216

1217
    /**
1218
     * Adapts a {@code Collector} to perform an additional finishing
1219
     * transformation.
1220
     * 
1221
     * <p>
1222
     * Unlike {@link Collectors#collectingAndThen(Collector, Function)} this
1223
     * method returns a
1224
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1225
     * collector</a> if the downstream collector is short-circuiting.
1226
     *
1227
     * @param <T> the type of the input elements
1228
     * @param <A> intermediate accumulation type of the downstream collector
1229
     * @param <R> result type of the downstream collector
1230
     * @param <RR> result type of the resulting collector
1231
     * @param downstream a collector
1232
     * @param finisher a function to be applied to the final result of the
1233
     *        downstream collector
1234
     * @return a collector which performs the action of the downstream
1235
     *         collector, followed by an additional finishing step
1236
     * @throws NullPointerException if downstream is null, or finisher is null.
1237
     * @see Collectors#collectingAndThen(Collector, Function)
1238
     * @since 0.4.0
1239
     */
1240
    public static <T, A, R, RR> Collector<T, A, RR> collectingAndThen(Collector<T, A, R> downstream,
1241
            Function<R, RR> finisher) {
1242
        Predicate<A> finished = finished(downstream);
1✔
1243
        if (finished != null) {
1✔
1244
            return new CancellableCollectorImpl<>(downstream.supplier(), downstream.accumulator(), downstream
1✔
1245
                    .combiner(), downstream.finisher().andThen(finisher), finished, downstream.characteristics()
1✔
1246
                            .contains(Characteristics.UNORDERED) ? UNORDERED_CHARACTERISTICS : NO_CHARACTERISTICS);
1✔
1247
        }
1248
        return Collectors.collectingAndThen(downstream, finisher);
1✔
1249
    }
1250

1251
    /**
1252
     * Returns a {@code Collector} which partitions the input elements according
1253
     * to a {@code Predicate}, reduces the values in each partition according to
1254
     * another {@code Collector}, and organizes them into a
1255
     * {@code Map<Boolean, D>} whose values are the result of the downstream
1256
     * reduction.
1257
     * 
1258
     * <p>
1259
     * Unlike {@link Collectors#partitioningBy(Predicate, Collector)} this
1260
     * method returns a
1261
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1262
     * collector</a> if the downstream collector is short-circuiting.
1263
     * 
1264
     * @param <T> the type of the input elements
1265
     * @param <A> the intermediate accumulation type of the downstream collector
1266
     * @param <D> the result type of the downstream reduction
1267
     * @param predicate a predicate used for classifying input elements
1268
     * @param downstream a {@code Collector} implementing the downstream
1269
     *        reduction
1270
     * @return a {@code Collector} implementing the cascaded partitioning
1271
     *         operation
1272
     * @throws NullPointerException if predicate is null, or downstream is null.
1273
     * @since 0.4.0
1274
     * @see Collectors#partitioningBy(Predicate, Collector)
1275
     */
1276
    public static <T, D, A> Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate,
1277
            Collector<? super T, A, D> downstream) {
1278
        Objects.requireNonNull(predicate);
1✔
1279
        Predicate<A> finished = finished(downstream);
1✔
1280
        if (finished != null) {
1✔
1281
            BiConsumer<A, ? super T> accumulator = downstream.accumulator();
1✔
1282
            return BooleanMap.partialCollector(downstream).asCancellable((map, t) -> accumulator.accept(predicate.test(
1✔
1283
                t) ? map.trueValue : map.falseValue, t), map -> finished.test(map.trueValue) && finished.test(
1✔
1284
                    map.falseValue));
1285
        }
1286
        return Collectors.partitioningBy(predicate, downstream);
1✔
1287
    }
1288

1289
    /**
1290
     * Adapts a {@code Collector} accepting elements of type {@code U} to one
1291
     * accepting elements of type {@code T} by applying a mapping function to
1292
     * each input element before accumulation.
1293
     *
1294
     * <p>
1295
     * Unlike {@link Collectors#mapping(Function, Collector)} this method
1296
     * returns a
1297
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1298
     * collector</a> if the downstream collector is short-circuiting.
1299
     * 
1300
     * @param <T> the type of the input elements
1301
     * @param <U> type of elements accepted by downstream collector
1302
     * @param <A> intermediate accumulation type of the downstream collector
1303
     * @param <R> result type of collector
1304
     * @param mapper a function to be applied to the input elements
1305
     * @param downstream a collector which will accept mapped values
1306
     * @return a collector which applies the mapping function to the input
1307
     *         elements and provides the mapped results to the downstream
1308
     *         collector
1309
     * @throws NullPointerException if mapper is null, or downstream is null.
1310
     * @see Collectors#mapping(Function, Collector)
1311
     * @since 0.4.0
1312
     */
1313
    public static <T, U, A, R> Collector<T, ?, R> mapping(Function<? super T, ? extends U> mapper,
1314
            Collector<? super U, A, R> downstream) {
1315
        Objects.requireNonNull(mapper);
1✔
1316
        Predicate<A> finished = finished(downstream);
1✔
1317
        if (finished != null) {
1✔
1318
            BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator();
1✔
1319
            return new CancellableCollectorImpl<>(downstream.supplier(), (acc, t) -> {
1✔
1320
                if (!finished.test(acc))
1✔
1321
                    downstreamAccumulator.accept(acc, mapper.apply(t));
1✔
1322
            }, downstream.combiner(), downstream.finisher(), finished, downstream.characteristics());
1✔
1323
        }
1324
        return Collectors.mapping(mapper, downstream);
1✔
1325
    }
1326

1327
    /**
1328
     * Returns a collector which collects input elements to the new {@code List}
1329
     * transforming them with the supplied function beforehand.
1330
     * 
1331
     * <p>
1332
     * This method behaves like
1333
     * {@code Collectors.mapping(mapper, Collectors.toList())}.
1334
     * 
1335
     * <p>
1336
     * There are no guarantees on the type, mutability, serializability, or
1337
     * thread-safety of the {@code List} returned.
1338
     * 
1339
     * @param <T> the type of the input elements
1340
     * @param <U> the resulting type of the mapper function
1341
     * @param mapper a function to be applied to the input elements
1342
     * @return a collector which applies the mapping function to the input
1343
     *         elements and collects the mapped results to the {@code List}
1344
     * @throws NullPointerException if mapper is null.
1345
     * @see #mapping(Function, Collector)
1346
     * @since 0.6.0
1347
     */
1348
    public static <T, U> Collector<T, ?, List<U>> mapping(Function<? super T, ? extends U> mapper) {
1349
        return Collectors.mapping(mapper, Collectors.toList());
1✔
1350
    }
1351

1352
    /**
1353
     * Adapts a {@code Collector} accepting elements of type {@code U} to one
1354
     * accepting elements of type {@code T} by applying a flat mapping function
1355
     * to each input element before accumulation. The flat mapping function maps
1356
     * an input element to a {@link Stream stream} covering zero or more output
1357
     * elements that are then accumulated downstream. Each mapped stream is
1358
     * {@link java.util.stream.BaseStream#close() closed} after its contents
1359
     * have been placed downstream. (If a mapped stream is {@code null} an empty
1360
     * stream is used, instead.)
1361
     * 
1362
     * <p>
1363
     * This method is similar to {@code Collectors.flatMapping} method which
1364
     * appears in JDK 9. However when downstream collector is
1365
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting</a>
1366
     * , this method will also return a short-circuiting collector.
1367
     * 
1368
     * @param <T> the type of the input elements
1369
     * @param <U> type of elements accepted by downstream collector
1370
     * @param <A> intermediate accumulation type of the downstream collector
1371
     * @param <R> result type of collector
1372
     * @param mapper a function to be applied to the input elements, which
1373
     *        returns a stream of results
1374
     * @param downstream a collector which will receive the elements of the
1375
     *        stream returned by mapper
1376
     * @return a collector which applies the mapping function to the input
1377
     *         elements and provides the flat mapped results to the downstream
1378
     *         collector
1379
     * @throws NullPointerException if mapper is null, or downstream is null.
1380
     * @since 0.4.1
1381
     */
1382
    public static <T, U, A, R> Collector<T, ?, R> flatMapping(Function<? super T, ? extends Stream<? extends U>> mapper,
1383
            Collector<? super U, A, R> downstream) {
1384
        Objects.requireNonNull(mapper);
1✔
1385
        BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator();
1✔
1386
        Predicate<A> finished = finished(downstream);
1✔
1387
        if (finished != null) {
1✔
1388
            return new CancellableCollectorImpl<>(downstream.supplier(), (acc, t) -> {
1✔
1389
                if (finished.test(acc))
1✔
1390
                    return;
1✔
1391
                try (Stream<? extends U> stream = mapper.apply(t)) {
1✔
1392
                    if (stream != null) {
1✔
1393
                        stream.spliterator().forEachRemaining(u -> {
1✔
1394
                            downstreamAccumulator.accept(acc, u);
1✔
1395
                            if (finished.test(acc))
1✔
1396
                                throw new CancelException();
1✔
1397
                        });
1✔
1398
                    }
1399
                } catch (CancelException ex) {
1✔
1400
                    // ignore
1401
                }
1✔
1402
            }, downstream.combiner(), downstream.finisher(), finished, downstream.characteristics());
1✔
1403
        }
1404
        return Collector.of(downstream.supplier(), (acc, t) -> {
1✔
1405
            try (Stream<? extends U> stream = mapper.apply(t)) {
1✔
1406
                if (stream != null) {
1✔
1407
                    stream.spliterator().forEachRemaining(u -> downstreamAccumulator.accept(acc, u));
1✔
1408
                }
1409
            }
1410
        }, downstream.combiner(), downstream.finisher(), downstream.characteristics().toArray(new Characteristics[0]));
1✔
1411
    }
1412

1413
    /**
1414
     * Returns a collector which launches a flat mapping function for each input
1415
     * element and collects the elements of the resulting streams to the flat
1416
     * {@code List}. Each mapped stream is
1417
     * {@link java.util.stream.BaseStream#close() closed} after its contents
1418
     * have been placed downstream. (If a mapped stream is {@code null} an empty
1419
     * stream is used, instead.)
1420
     * 
1421
     * <p>
1422
     * This method behaves like {@code flatMapping(mapper, Collectors.toList())}
1423
     * .
1424
     * 
1425
     * <p>
1426
     * There are no guarantees on the type, mutability, serializability, or
1427
     * thread-safety of the {@code List} returned.
1428
     * 
1429
     * @param <T> the type of the input elements
1430
     * @param <U> type of the resulting elements
1431
     * @param mapper a function to be applied to the input elements, which
1432
     *        returns a stream of results
1433
     * @return a collector which applies the mapping function to the input
1434
     *         elements and collects the flat mapped results to the {@code List}
1435
     * @throws NullPointerException if mapper is null.
1436
     * @since 0.6.0
1437
     */
1438
    public static <T, U> Collector<T, ?, List<U>> flatMapping(
1439
            Function<? super T, ? extends Stream<? extends U>> mapper) {
1440
        return flatMapping(mapper, Collectors.toList());
1✔
1441
    }
1442

1443
    /**
1444
     * Returns a {@code Collector} which passes only those elements to the
1445
     * specified downstream collector which match given predicate.
1446
     *
1447
     * <p>
1448
     * This method returns a
1449
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1450
     * collector</a> if downstream collector is short-circuiting.
1451
     * 
1452
     * <p>
1453
     * The operation performed by the returned collector is equivalent to
1454
     * {@code stream.filter(predicate).collect(downstream)}. This collector is
1455
     * mostly useful as a downstream collector in cascaded operation involving
1456
     * {@link #pairing(Collector, Collector, BiFunction)} collector.
1457
     *
1458
     * <p>
1459
     * This method is similar to {@code Collectors.filtering} method which
1460
     * appears in JDK 9. However when downstream collector is
1461
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting</a>
1462
     * , this method will also return a short-circuiting collector.
1463
     * 
1464
     * @param <T> the type of the input elements
1465
     * @param <A> intermediate accumulation type of the downstream collector
1466
     * @param <R> result type of collector
1467
     * @param predicate a filter function to be applied to the input elements
1468
     * @param downstream a collector which will accept filtered values
1469
     * @return a collector which applies the predicate to the input elements and
1470
     *         provides the elements for which predicate returned true to the
1471
     *         downstream collector
1472
     * @throws NullPointerException if predicate is null, or downstream is null.
1473
     * @see #pairing(Collector, Collector, BiFunction)
1474
     * @since 0.4.0
1475
     */
1476
    public static <T, A, R> Collector<T, ?, R> filtering(Predicate<? super T> predicate,
1477
            Collector<T, A, R> downstream) {
1478
        Objects.requireNonNull(predicate);
1✔
1479
        BiConsumer<A, T> downstreamAccumulator = downstream.accumulator();
1✔
1480
        BiConsumer<A, T> accumulator = (acc, t) -> {
1✔
1481
            if (predicate.test(t))
1✔
1482
                downstreamAccumulator.accept(acc, t);
1✔
1483
        };
1✔
1484
        Predicate<A> finished = finished(downstream);
1✔
1485
        if (finished != null) {
1✔
1486
            return new CancellableCollectorImpl<>(downstream.supplier(), accumulator, downstream.combiner(), downstream
1✔
1487
                    .finisher(), finished, downstream.characteristics());
1✔
1488
        }
1489
        return Collector.of(downstream.supplier(), accumulator, downstream.combiner(), downstream.finisher(), downstream
1✔
1490
                .characteristics().toArray(new Characteristics[0]));
1✔
1491
    }
1492

1493
    /**
1494
     * Returns a {@code Collector} which filters input elements by the supplied
1495
     * predicate, collecting them to the list.
1496
     *
1497
     * <p>
1498
     * This method behaves like
1499
     * {@code filtering(predicate, Collectors.toList())}.
1500
     * 
1501
     * <p>
1502
     * There are no guarantees on the type, mutability, serializability, or
1503
     * thread-safety of the {@code List} returned.
1504
     * 
1505
     * @param <T> the type of the input elements
1506
     * @param predicate a filter function to be applied to the input elements
1507
     * @return a collector which applies the predicate to the input elements and
1508
     *         collects the elements for which predicate returned true to the
1509
     *         {@code List}
1510
     * @throws NullPointerException if predicate is null.
1511
     * @see #filtering(Predicate, Collector)
1512
     * @since 0.6.0
1513
     */
1514
    public static <T> Collector<T, ?, List<T>> filtering(Predicate<? super T> predicate) {
1515
        return filtering(predicate, Collectors.toList());
1✔
1516
    }
1517

1518
    /**
1519
     * Returns a {@code Collector} which performs the bitwise-and operation of a
1520
     * integer-valued function applied to the input elements. If no elements are
1521
     * present, the result is empty {@link OptionalInt}.
1522
     *
1523
     * <p>
1524
     * This method returns a
1525
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1526
     * collector</a>: it may not process all the elements if the result is zero.
1527
     * 
1528
     * @param <T> the type of the input elements
1529
     * @param mapper a function extracting the property to be processed
1530
     * @return a {@code Collector} that produces the bitwise-and operation of a
1531
     *         derived property
1532
     * @throws NullPointerException if mapper is null.
1533
     * @since 0.4.0
1534
     */
1535
    public static <T> Collector<T, ?, OptionalInt> andingInt(ToIntFunction<T> mapper) {
1536
        Objects.requireNonNull(mapper);
1✔
1537
        return new CancellableCollectorImpl<>(PrimitiveBox::new, (acc, t) -> {
1✔
1538
            if (!acc.b) {
1✔
1539
                acc.i = mapper.applyAsInt(t);
1✔
1540
                acc.b = true;
1✔
1541
            } else {
1542
                acc.i &= mapper.applyAsInt(t);
1✔
1543
            }
1544
        }, (acc1, acc2) -> {
1✔
1545
            if (!acc1.b)
1✔
1546
                return acc2;
1✔
1547
            if (!acc2.b)
1✔
1548
                return acc1;
1✔
1549
            acc1.i &= acc2.i;
1✔
1550
            return acc1;
1✔
1551
        }, PrimitiveBox::asInt, acc -> acc.b && acc.i == 0, UNORDERED_CHARACTERISTICS);
1✔
1552
    }
1553

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

1590
    /**
1591
     * Returns a {@code Collector} which computes a common prefix of input
1592
     * {@code CharSequence} objects returning the result as {@code String}. For
1593
     * empty input the empty {@code String} is returned.
1594
     *
1595
     * <p>
1596
     * The returned {@code Collector} handles specially Unicode surrogate pairs:
1597
     * the returned prefix may end with
1598
     * <a href="http://www.unicode.org/glossary/#high_surrogate_code_unit">
1599
     * Unicode high-surrogate code unit</a> only if it's not succeeded by
1600
     * <a href="http://www.unicode.org/glossary/#low_surrogate_code_unit">
1601
     * Unicode low-surrogate code unit</a> in any of the input sequences.
1602
     * Normally the ending high-surrogate code unit is removed from the prefix.
1603
     * 
1604
     * <p>
1605
     * This method returns a
1606
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1607
     * collector</a>: it may not process all the elements if the common prefix
1608
     * is empty.
1609
     * 
1610
     * @return a {@code Collector} which computes a common prefix.
1611
     * @since 0.5.0
1612
     */
1613
    public static Collector<CharSequence, ?, String> commonPrefix() {
1614
        BiConsumer<ObjIntBox<CharSequence>, CharSequence> accumulator = (acc, t) -> {
1✔
1615
            if (acc.b == -1) {
1✔
1616
                acc.a = t;
1✔
1617
                acc.b = t.length();
1✔
1618
            } else if (acc.b > 0) {
1✔
1619
                if (t.length() < acc.b)
1✔
1620
                    acc.b = t.length();
1✔
1621
                for (int i = 0; i < acc.b; i++) {
1✔
1622
                    if (acc.a.charAt(i) != t.charAt(i)) {
1✔
1623
                        if (i > 0 && Character.isHighSurrogate(t.charAt(i - 1)) && (Character.isLowSurrogate(t.charAt(
1✔
1624
                            i)) || Character.isLowSurrogate(acc.a.charAt(i))))
1✔
1625
                            i--;
1✔
1626
                        acc.b = i;
1✔
1627
                        break;
1✔
1628
                    }
1629
                }
1630
            }
1631
        };
1✔
1632
        return new CancellableCollectorImpl<>(() -> new ObjIntBox<>(null, -1), accumulator, (acc1, acc2) -> {
1✔
1633
            if (acc1.b == -1)
1✔
1634
                return acc2;
1✔
1635
            if (acc2.b != -1)
1✔
1636
                accumulator.accept(acc1, acc2.a.subSequence(0, acc2.b));
1✔
1637
            return acc1;
1✔
1638
        }, acc -> acc.a == null ? "" : acc.a.subSequence(0, acc.b).toString(), acc -> acc.b == 0,
1✔
1639
                UNORDERED_CHARACTERISTICS);
1640
    }
1641

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

1696
    /**
1697
     * Returns a collector which collects input elements into {@code List}
1698
     * removing the elements following their dominator element. The dominator
1699
     * elements are defined according to given isDominator {@code BiPredicate}.
1700
     * The isDominator relation must be transitive (if A dominates over B and B
1701
     * dominates over C, then A also dominates over C).
1702
     * 
1703
     * <p>
1704
     * This operation is similar to
1705
     * {@code streamEx.collapse(isDominator).toList()}. The important difference
1706
     * is that in this method {@code BiPredicate} accepts not the adjacent
1707
     * stream elements, but the leftmost element of the series (current
1708
     * dominator) and the current element.
1709
     * 
1710
     * <p>
1711
     * For example, consider the stream of numbers:
1712
     * 
1713
     * <pre>{@code
1714
     * StreamEx<Integer> stream = StreamEx.of(1, 5, 3, 4, 2, 7);
1715
     * }</pre>
1716
     * 
1717
     * <p>
1718
     * Using {@code stream.collapse((a, b) -> a >= b).toList()} you will get the
1719
     * numbers which are bigger than their immediate predecessor (
1720
     * {@code [1, 5, 4, 7]}), because (3, 4) pair is not collapsed. However
1721
     * using {@code stream.collect(dominators((a, b) -> a >= b))} you will get
1722
     * the numbers which are bigger than any predecessor ({@code [1, 5, 7]}) as
1723
     * 5 is the dominator element for the subsequent 3, 4 and 2.
1724
     * 
1725
     * @param <T> type of the input elements.
1726
     * @param isDominator a non-interfering, stateless, transitive
1727
     *        {@code BiPredicate} which returns true if the first argument is
1728
     *        the dominator for the second argument.
1729
     * @return a collector which collects input element into {@code List}
1730
     *         leaving only dominator elements.
1731
     * @throws NullPointerException if isDominator is null.
1732
     * @see StreamEx#collapse(BiPredicate)
1733
     * @since 0.5.1
1734
     */
1735
    public static <T> Collector<T, ?, List<T>> dominators(BiPredicate<? super T, ? super T> isDominator) {
1736
        Objects.requireNonNull(isDominator);
1✔
1737
        return Collector.of(ArrayList::new, (acc, t) -> {
1✔
1738
            if (acc.isEmpty() || !isDominator.test(acc.get(acc.size() - 1), t))
1✔
1739
                acc.add(t);
1✔
1740
        }, (acc1, acc2) -> {
1✔
1741
            if (acc1.isEmpty())
1✔
1742
                return acc2;
1✔
1743
            int i = 0, l = acc2.size();
1✔
1744
            T last = acc1.get(acc1.size() - 1);
1✔
1745
            while (i < l && isDominator.test(last, acc2.get(i)))
1✔
1746
                i++;
1✔
1747
            if (i < l)
1✔
1748
                acc1.addAll(acc2.subList(i, l));
1✔
1749
            return acc1;
1✔
1750
        });
1751
    }
1752

1753
    /**
1754
     * Returns a {@code Collector} which performs downstream reduction if all
1755
     * elements satisfy the {@code Predicate}. The result is described as an
1756
     * {@code Optional<R>}.
1757
     * 
1758
     * <p>
1759
     * The resulting collector returns an empty optional if at least one input
1760
     * element does not satisfy the predicate. Otherwise it returns an optional
1761
     * which contains the result of the downstream collector.
1762
     * 
1763
     * <p>
1764
     * This method returns a
1765
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1766
     * collector</a>: it may not process all the elements if some of items don't
1767
     * satisfy the predicate or if downstream collector is a short-circuiting
1768
     * collector.
1769
     * 
1770
     * <p>
1771
     * It's guaranteed that the downstream collector is not called for elements
1772
     * which don't satisfy the predicate.
1773
     *
1774
     * @param <T> the type of input elements
1775
     * @param <A> intermediate accumulation type of the downstream collector
1776
     * @param <R> result type of the downstream collector
1777
     * @param predicate a non-interfering, stateless predicate to checks whether
1778
     *        collector should proceed with element
1779
     * @param downstream a {@code Collector} implementing the downstream
1780
     *        reduction
1781
     * @return a {@code Collector} witch performs downstream reduction if all
1782
     *         elements satisfy the predicate
1783
     * @throws NullPointerException if mapper is null.
1784
     * @see Stream#allMatch(Predicate)
1785
     * @see AbstractStreamEx#dropWhile(Predicate)
1786
     * @see AbstractStreamEx#takeWhile(Predicate)
1787
     * @since 0.6.3
1788
     */
1789
    public static <T, A, R> Collector<T, ?, Optional<R>> ifAllMatch(Predicate<T> predicate,
1790
            Collector<T, A, R> downstream) {
1791
        Objects.requireNonNull(predicate);
1✔
1792
        Predicate<A> finished = finished(downstream);
1✔
1793
        Supplier<A> supplier = downstream.supplier();
1✔
1794
        BiConsumer<A, T> accumulator = downstream.accumulator();
1✔
1795
        BinaryOperator<A> combiner = downstream.combiner();
1✔
1796
        return new CancellableCollectorImpl<>(
1✔
1797
                () -> new PairBox<>(supplier.get(), Boolean.TRUE),
1✔
1798
                (acc, t) -> {
1799
                    if (acc.b && predicate.test(t)) {
1✔
1800
                        accumulator.accept(acc.a, t);
1✔
1801
                    } else {
1802
                        acc.b = Boolean.FALSE;
1✔
1803
                    }
1804
                },
1✔
1805
                (acc1, acc2) -> {
1806
                    if (acc1.b && acc2.b) {
1✔
1807
                        acc1.a = combiner.apply(acc1.a, acc2.a);
1✔
1808
                    } else {
1809
                        acc1.b = Boolean.FALSE;
1✔
1810
                    }
1811
                    return acc1;
1✔
1812
                },
1813
                acc -> acc.b ? Optional.of(downstream.finisher().apply(acc.a)) : Optional.empty(),
1✔
1814
                finished == null ? acc -> !acc.b : acc -> !acc.b || finished.test(acc.a),
1✔
1815
                downstream.characteristics().contains(Characteristics.UNORDERED) ? UNORDERED_CHARACTERISTICS
1✔
1816
                        : NO_CHARACTERISTICS);
1✔
1817
    }
1818

1819
    /**
1820
     * Returns a {@code Collector} which performs a possibly short-circuiting reduction of its
1821
     * input elements under a specified {@code BinaryOperator}. The result
1822
     * is described as an {@code Optional<T>}.
1823
     *
1824
     * <p>
1825
     * This collector behaves like {@link Collectors#reducing(BinaryOperator)}. However,
1826
     * it additionally accepts a zero element (also known as absorbing element). When zero element
1827
     * is passed to the accumulator then the result must be zero as well. So the collector
1828
     * takes the advantage of this and may short-circuit if zero is reached during the collection.
1829
     *
1830
     * <p>
1831
     * This method returns a
1832
     * <a href="package-summary.html#ShortCircuitReduction">short-circuiting
1833
     * collector</a>: it may not process all the elements if the result of reduction is equal to zero.
1834
     *
1835
     * <p>
1836
     * This collector is mostly useful as a downstream collector. To perform simple
1837
     * short-circuiting reduction, use {@link AbstractStreamEx#reduceWithZero(Object, BinaryOperator)}
1838
     * instead.
1839
     *
1840
     * @param zero zero element
1841
     * @param op an <a href="package-summary.html#Associativity">associative</a>
1842
     *        , <a href="package-summary.html#NonInterference">non-interfering
1843
     *        </a>, <a href="package-summary.html#Statelessness">stateless</a>
1844
     *        function to combine two elements into one.
1845
     * @param <T> the type of input elements
1846
     * @return a collector which returns an {@link Optional} describing the reduction result.
1847
     *         For empty stream an empty {@code Optional} is returned.
1848
     * @throws NullPointerException if op is null or the result of reduction is null
1849
     * @see #reducingWithZero(Object, Object, BinaryOperator)
1850
     * @see AbstractStreamEx#reduceWithZero(Object, BinaryOperator)
1851
     * @see Collectors#reducing(BinaryOperator)
1852
     * @since 0.7.3
1853
     */
1854
    public static <T> Collector<T, ?, Optional<T>> reducingWithZero(T zero, BinaryOperator<T> op) {
1855
        Objects.requireNonNull(op);
1✔
1856
        // acc.b: 0 = no element, 1 = has element, 2 = zero reached
1857
        return new CancellableCollectorImpl<>(
1✔
1858
            () -> new ObjIntBox<T>(null, 0),
1✔
1859
            (acc, t) -> {
1860
                if (acc.b != 2) {
1✔
1861
                    if (acc.b == 1) {
1✔
1862
                        t = op.apply(t, acc.a);
1✔
1863
                    }
1864
                    if (Objects.equals(t, zero)) {
1✔
1865
                        acc.b = 2;
1✔
1866
                        acc.a = zero;
1✔
1867
                    } else {
1868
                        acc.b = 1;
1✔
1869
                        acc.a = t;
1✔
1870
                    }
1871
                }
1872
            },
1✔
1873
            (acc1, acc2) -> {
1874
                if (acc1.b == 0 || acc2.b == 2) return acc2;
1✔
1875
                if (acc2.b == 0 || acc1.b == 2) return acc1;
1✔
1876
                T t = op.apply(acc1.a, acc2.a);
1✔
1877
                if (Objects.equals(t, zero)) {
1✔
1878
                    acc1.b = 2;
1✔
1879
                    acc1.a = zero;
1✔
1880
                } else {
1881
                    acc1.a = t;
1✔
1882
                }
1883
                return acc1;
1✔
1884
            },
1885
            acc -> acc.b == 0 ? Optional.empty() : Optional.of(acc.a),
1✔
1886
            acc -> acc.b == 2,
1✔
1887
            UNORDERED_CHARACTERISTICS
1888
        );
1889
    }
1890

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

© 2025 Coveralls, Inc