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

amaembo / streamex / #683

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

push

amaembo
Update workflow versions in test.yml

5804 of 5820 relevant lines covered (99.73%)

1.0 hits per line

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

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

18
import org.jspecify.annotations.Nullable;
19

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

26
/* package */interface Internals {
27
    int INITIAL_SIZE = 128;
28
    Function<int[], Integer> UNBOX_INT = box -> box[0];
1✔
29
    Function<long[], Long> UNBOX_LONG = box -> box[0];
1✔
30
    Function<double[], Double> UNBOX_DOUBLE = box -> box[0];
1✔
31
    Object NONE = new Object();
1✔
32
    Set<Characteristics> NO_CHARACTERISTICS = EnumSet.noneOf(Characteristics.class);
1✔
33
    Set<Characteristics> UNORDERED_CHARACTERISTICS = EnumSet.of(Characteristics.UNORDERED);
1✔
34
    Set<Characteristics> UNORDERED_ID_CHARACTERISTICS = EnumSet.of(Characteristics.UNORDERED,
1✔
35
        Characteristics.IDENTITY_FINISH);
36
    Set<Characteristics> ID_CHARACTERISTICS = EnumSet.of(Characteristics.IDENTITY_FINISH);
1✔
37
    boolean IMMUTABLE_TO_LIST = isImmutableToSetToList();
1✔
38

39
    static boolean isImmutableToSetToList() {
40
        try {
41
            return Boolean.parseBoolean(System.getProperty("streamex.default.immutable", "false"));
1✔
42
        } catch (SecurityException e) {
×
43
            return false;
×
44
        }
45
    }
46

47
    static void checkNonNegative(String name, int value) {
48
        if (value < 0) {
1✔
49
            throw new IllegalArgumentException(name + " must be non-negative: " + value);
1✔
50
        }
51
    }
1✔
52

53
    final class ByteBuffer {
54
        int size = 0;
1✔
55
        byte[] data;
56

57
        ByteBuffer() {
1✔
58
            data = new byte[INITIAL_SIZE];
1✔
59
        }
1✔
60

61
        ByteBuffer(int size) {
1✔
62
            data = new byte[size];
1✔
63
        }
1✔
64

65
        void add(int n) {
66
            if (data.length == size) {
1✔
67
                data = Arrays.copyOf(data, data.length * 2);
1✔
68
            }
69
            data[size++] = (byte) n;
1✔
70
        }
1✔
71

72
        void addUnsafe(int n) {
73
            data[size++] = (byte) n;
1✔
74
        }
1✔
75

76
        void addAll(ByteBuffer buf) {
77
            if (data.length < buf.size + size) {
1✔
78
                data = Arrays.copyOf(data, buf.size + size);
1✔
79
            }
80
            System.arraycopy(buf.data, 0, data, size, buf.size);
1✔
81
            size += buf.size;
1✔
82
        }
1✔
83

84
        byte[] toArray() {
85
            return data.length == size ? data : Arrays.copyOfRange(data, 0, size);
1✔
86
        }
87
    }
88

89
    final class CharBuffer {
90
        int size = 0;
1✔
91
        char[] data;
92

93
        CharBuffer() {
1✔
94
            data = new char[INITIAL_SIZE];
1✔
95
        }
1✔
96

97
        CharBuffer(int size) {
1✔
98
            data = new char[size];
1✔
99
        }
1✔
100

101
        void add(int n) {
102
            if (data.length == size) {
1✔
103
                data = Arrays.copyOf(data, data.length * 2);
1✔
104
            }
105
            data[size++] = (char) n;
1✔
106
        }
1✔
107

108
        void addUnsafe(int n) {
109
            data[size++] = (char) n;
1✔
110
        }
1✔
111

112
        void addAll(CharBuffer buf) {
113
            if (data.length < buf.size + size) {
1✔
114
                data = Arrays.copyOf(data, buf.size + size);
1✔
115
            }
116
            System.arraycopy(buf.data, 0, data, size, buf.size);
1✔
117
            size += buf.size;
1✔
118
        }
1✔
119

120
        char[] toArray() {
121
            return data.length == size ? data : Arrays.copyOfRange(data, 0, size);
1✔
122
        }
123
    }
124

125
    final class ShortBuffer {
126
        int size = 0;
1✔
127
        short[] data;
128

129
        ShortBuffer() {
1✔
130
            data = new short[INITIAL_SIZE];
1✔
131
        }
1✔
132

133
        ShortBuffer(int size) {
1✔
134
            data = new short[size];
1✔
135
        }
1✔
136

137
        void add(int n) {
138
            if (data.length == size) {
1✔
139
                data = Arrays.copyOf(data, data.length * 2);
1✔
140
            }
141
            data[size++] = (short) n;
1✔
142
        }
1✔
143

144
        void addUnsafe(int n) {
145
            data[size++] = (short) n;
1✔
146
        }
1✔
147

148
        void addAll(ShortBuffer buf) {
149
            if (data.length < buf.size + size) {
1✔
150
                data = Arrays.copyOf(data, buf.size + size);
1✔
151
            }
152
            System.arraycopy(buf.data, 0, data, size, buf.size);
1✔
153
            size += buf.size;
1✔
154
        }
1✔
155

156
        short[] toArray() {
157
            return data.length == size ? data : Arrays.copyOfRange(data, 0, size);
1✔
158
        }
159
    }
160

161
    final class FloatBuffer {
162
        int size = 0;
1✔
163
        float[] data;
164

165
        FloatBuffer() {
1✔
166
            data = new float[INITIAL_SIZE];
1✔
167
        }
1✔
168

169
        FloatBuffer(int size) {
1✔
170
            data = new float[size];
1✔
171
        }
1✔
172

173
        void add(double n) {
174
            if (data.length == size) {
1✔
175
                data = Arrays.copyOf(data, data.length * 2);
1✔
176
            }
177
            data[size++] = (float) n;
1✔
178
        }
1✔
179

180
        void addUnsafe(double n) {
181
            data[size++] = (float) n;
1✔
182
        }
1✔
183

184
        void addAll(FloatBuffer buf) {
185
            if (data.length < buf.size + size) {
1✔
186
                data = Arrays.copyOf(data, buf.size + size);
1✔
187
            }
188
            System.arraycopy(buf.data, 0, data, size, buf.size);
1✔
189
            size += buf.size;
1✔
190
        }
1✔
191

192
        float[] toArray() {
193
            return data.length == size ? data : Arrays.copyOfRange(data, 0, size);
1✔
194
        }
195
    }
196

197
    final class IntBuffer {
198
        int size = 0;
1✔
199
        int[] data;
200

201
        IntBuffer() {
1✔
202
            data = new int[INITIAL_SIZE];
1✔
203
        }
1✔
204

205
        IntBuffer(int size) {
1✔
206
            data = new int[size];
1✔
207
        }
1✔
208

209
        void add(int n) {
210
            if (data.length == size) {
1✔
211
                data = Arrays.copyOf(data, data.length * 2);
1✔
212
            }
213
            data[size++] = n;
1✔
214
        }
1✔
215

216
        void addAll(IntBuffer buf) {
217
            if (data.length < buf.size + size) {
1✔
218
                data = Arrays.copyOf(data, buf.size + size);
1✔
219
            }
220
            System.arraycopy(buf.data, 0, data, size, buf.size);
1✔
221
            size += buf.size;
1✔
222
        }
1✔
223
        
224
        IntStreamEx stream() {
225
            return IntStreamEx.of(data, 0, size);
1✔
226
        }
227

228
        int[] toArray() {
229
            return data.length == size ? data : Arrays.copyOfRange(data, 0, size);
1✔
230
        }
231
    }
232

233
    final class LongBuffer {
234
        int size = 0;
1✔
235
        long[] data;
236

237
        LongBuffer() {
1✔
238
            data = new long[INITIAL_SIZE];
1✔
239
        }
1✔
240

241
        LongBuffer(int size) {
1✔
242
            data = new long[size];
1✔
243
        }
1✔
244

245
        void add(long n) {
246
            if (data.length == size) {
1✔
247
                data = Arrays.copyOf(data, data.length * 2);
1✔
248
            }
249
            data[size++] = n;
1✔
250
        }
1✔
251

252
        void addAll(LongBuffer buf) {
253
            if (data.length < buf.size + size) {
1✔
254
                data = Arrays.copyOf(data, buf.size + size);
1✔
255
            }
256
            System.arraycopy(buf.data, 0, data, size, buf.size);
1✔
257
            size += buf.size;
1✔
258
        }
1✔
259

260
        LongStreamEx stream() {
261
            return LongStreamEx.of(data, 0, size);
1✔
262
        }
263

264
        long[] toArray() {
265
            return data.length == size ? data : Arrays.copyOfRange(data, 0, size);
1✔
266
        }
267
    }
268

269
    final class DoubleBuffer {
270
        int size = 0;
1✔
271
        double[] data;
272

273
        DoubleBuffer() {
1✔
274
            data = new double[INITIAL_SIZE];
1✔
275
        }
1✔
276

277
        DoubleBuffer(int size) {
1✔
278
            data = new double[size];
1✔
279
        }
1✔
280

281
        void add(double n) {
282
            if (data.length == size) {
1✔
283
                data = Arrays.copyOf(data, data.length * 2);
1✔
284
            }
285
            data[size++] = n;
1✔
286
        }
1✔
287

288
        void addAll(DoubleBuffer buf) {
289
            if (data.length < buf.size + size) {
1✔
290
                data = Arrays.copyOf(data, buf.size + size);
1✔
291
            }
292
            System.arraycopy(buf.data, 0, data, size, buf.size);
1✔
293
            size += buf.size;
1✔
294
        }
1✔
295

296
        DoubleStreamEx stream() {
297
            return DoubleStreamEx.of(data, 0, size);
1✔
298
        }
299

300
        double[] toArray() {
301
            return data.length == size ? data : Arrays.copyOfRange(data, 0, size);
1✔
302
        }
303
    }
304

305
    final class BooleanMap<T> extends AbstractMap<Boolean, T> {
306
        T trueValue, falseValue;
307

308
        BooleanMap(T trueValue, T falseValue) {
1✔
309
            this.trueValue = trueValue;
1✔
310
            this.falseValue = falseValue;
1✔
311
        }
1✔
312

313
        @Override
314
        public boolean containsKey(Object key) {
315
            return key instanceof Boolean;
1✔
316
        }
317

318
        @Override
319
        public T get(Object key) {
320
            if (Boolean.TRUE.equals(key))
1✔
321
                return trueValue;
1✔
322
            if (Boolean.FALSE.equals(key))
1✔
323
                return falseValue;
1✔
324
            return null;
1✔
325
        }
326

327
        @Override
328
        public Set<Map.Entry<Boolean, T>> entrySet() {
329
            return new AbstractSet<Map.Entry<Boolean, T>>() {
1✔
330
                @Override
331
                public Iterator<Map.Entry<Boolean, T>> iterator() {
332
                    return Arrays.<Map.Entry<Boolean, T>>asList(new SimpleEntry<>(Boolean.TRUE, trueValue),
1✔
333
                        new SimpleEntry<>(Boolean.FALSE, falseValue)).iterator();
1✔
334
                }
335

336
                @Override
337
                public int size() {
338
                    return 2;
1✔
339
                }
340
            };
341
        }
342

343
        @Override
344
        public int size() {
345
            return 2;
1✔
346
        }
347

348
        @SuppressWarnings({ "unchecked", "rawtypes" })
349
        static <A, R> PartialCollector<BooleanMap<A>, Map<Boolean, R>> partialCollector(Collector<?, A, R> downstream) {
350
            Supplier<A> downstreamSupplier = downstream.supplier();
1✔
351
            Supplier<BooleanMap<A>> supplier = () -> new BooleanMap<>(downstreamSupplier.get(), downstreamSupplier
1✔
352
                    .get());
1✔
353
            BinaryOperator<A> downstreamCombiner = downstream.combiner();
1✔
354
            BiConsumer<BooleanMap<A>, BooleanMap<A>> merger = (left, right) -> {
1✔
355
                left.trueValue = downstreamCombiner.apply(left.trueValue, right.trueValue);
1✔
356
                left.falseValue = downstreamCombiner.apply(left.falseValue, right.falseValue);
1✔
357
            };
1✔
358
            if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
1✔
359
                return (PartialCollector) new PartialCollector<>(supplier, merger, Function.identity(),
1✔
360
                        ID_CHARACTERISTICS);
361
            }
362
            Function<A, R> downstreamFinisher = downstream.finisher();
1✔
363
            return new PartialCollector<>(supplier, merger, par -> new BooleanMap<>(downstreamFinisher
1✔
364
                    .apply(par.trueValue), downstreamFinisher.apply(par.falseValue)), NO_CHARACTERISTICS);
1✔
365
        }
366
    }
367

368
    abstract class BaseCollector<T, A, R> implements MergingCollector<T, A, R> {
369
        final Supplier<A> supplier;
370
        final BiConsumer<A, A> merger;
371
        final Function<A, R> finisher;
372
        final Set<Characteristics> characteristics;
373

374
        BaseCollector(Supplier<A> supplier, BiConsumer<A, A> merger, Function<A, R> finisher,
375
                Set<Characteristics> characteristics) {
1✔
376
            this.supplier = supplier;
1✔
377
            this.merger = merger;
1✔
378
            this.finisher = finisher;
1✔
379
            this.characteristics = characteristics;
1✔
380
        }
1✔
381

382
        @Override
383
        public Set<Characteristics> characteristics() {
384
            return characteristics;
1✔
385
        }
386

387
        @Override
388
        public Supplier<A> supplier() {
389
            return supplier;
1✔
390
        }
391

392
        @Override
393
        public Function<A, R> finisher() {
394
            return finisher;
1✔
395
        }
396

397
        @Override
398
        public BiConsumer<A, A> merger() {
399
            return merger;
1✔
400
        }
401
    }
402

403
    final class PartialCollector<A, R> extends BaseCollector<Object, A, R> {
404
        PartialCollector(Supplier<A> supplier, BiConsumer<A, A> merger, Function<A, R> finisher,
405
                Set<Characteristics> characteristics) {
406
            super(supplier, merger, finisher, characteristics);
1✔
407
        }
1✔
408

409
        @Override
410
        public BiConsumer<A, Object> accumulator() {
411
            throw new UnsupportedOperationException();
1✔
412
        }
413

414
        IntCollector<A, R> asInt(ObjIntConsumer<A> intAccumulator) {
415
            return new IntCollectorImpl<>(supplier, intAccumulator, merger, finisher, characteristics);
1✔
416
        }
417

418
        LongCollector<A, R> asLong(ObjLongConsumer<A> longAccumulator) {
419
            return new LongCollectorImpl<>(supplier, longAccumulator, merger, finisher, characteristics);
1✔
420
        }
421

422
        DoubleCollector<A, R> asDouble(ObjDoubleConsumer<A> doubleAccumulator) {
423
            return new DoubleCollectorImpl<>(supplier, doubleAccumulator, merger, finisher, characteristics);
1✔
424
        }
425

426
        <T> Collector<T, A, R> asRef(BiConsumer<A, T> accumulator) {
427
            return Collector.of(supplier, accumulator, combiner(), finisher, characteristics
1✔
428
                    .toArray(new Characteristics[0]));
1✔
429
        }
430

431
        <T> Collector<T, A, R> asCancellable(BiConsumer<A, T> accumulator, Predicate<A> finished) {
432
            return new CancellableCollectorImpl<>(supplier, accumulator, combiner(), finisher, finished,
1✔
433
                    characteristics);
434
        }
435

436
        static PartialCollector<int[], Integer> intSum() {
437
            return new PartialCollector<>(() -> new int[1], (box1, box2) -> box1[0] += box2[0], UNBOX_INT,
1✔
438
                    UNORDERED_CHARACTERISTICS);
439
        }
440

441
        static PartialCollector<long[], Long> longSum() {
442
            return new PartialCollector<>(() -> new long[1], (box1, box2) -> box1[0] += box2[0], UNBOX_LONG,
1✔
443
                    UNORDERED_CHARACTERISTICS);
444
        }
445

446
        static PartialCollector<ObjIntBox<BitSet>, boolean[]> booleanArray() {
447
            return new PartialCollector<>(() -> new ObjIntBox<>(new BitSet(), 0), (box1, box2) -> {
1✔
448
                box2.a.stream().forEach(i -> box1.a.set(i + box1.b));
1✔
449
                box1.b = StrictMath.addExact(box1.b, box2.b);
1✔
450
            }, box -> {
1✔
451
                boolean[] res = new boolean[box.b];
1✔
452
                box.a.stream().forEach(i -> res[i] = true);
1✔
453
                return res;
1✔
454
            }, NO_CHARACTERISTICS);
455
        }
456

457
        @SuppressWarnings("unchecked")
458
        static <K, D, A, M extends Map<K, D>> PartialCollector<Map<K, A>, M> grouping(Supplier<M> mapFactory,
459
                Collector<?, A, D> downstream) {
460
            BinaryOperator<A> downstreamMerger = downstream.combiner();
1✔
461
            BiConsumer<Map<K, A>, Map<K, A>> merger = (map1, map2) -> {
1✔
462
                for (Map.Entry<K, A> e : map2.entrySet())
1✔
463
                    map1.merge(e.getKey(), e.getValue(), downstreamMerger);
1✔
464
            };
1✔
465

466
            if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
1✔
467
                return (PartialCollector<Map<K, A>, M>) new PartialCollector<>((Supplier<Map<K, A>>) mapFactory,
1✔
468
                        merger, Function.identity(), ID_CHARACTERISTICS);
1✔
469
            }
470
            Function<A, D> downstreamFinisher = downstream.finisher();
1✔
471
            return new PartialCollector<>((Supplier<Map<K, A>>) mapFactory, merger, map -> {
1✔
472
                map.replaceAll((k, v) -> ((Function<A, A>) downstreamFinisher).apply(v));
1✔
473
                return (M) map;
1✔
474
            }, NO_CHARACTERISTICS);
475
        }
476

477
        static PartialCollector<StringBuilder, String> joining(CharSequence delimiter, CharSequence prefix,
478
                CharSequence suffix, boolean hasPS) {
479
            BiConsumer<StringBuilder, StringBuilder> merger = (sb1, sb2) -> {
1✔
480
                if (sb2.length() > 0) {
1✔
481
                    if (sb1.length() > 0)
1✔
482
                        sb1.append(delimiter);
1✔
483
                    sb1.append(sb2);
1✔
484
                }
485
            };
1✔
486
            Supplier<StringBuilder> supplier = StringBuilder::new;
1✔
487
            if (hasPS)
1✔
488
                return new PartialCollector<>(supplier, merger, sb -> String.valueOf(prefix) + sb + suffix,
1✔
489
                        NO_CHARACTERISTICS);
490
            return new PartialCollector<>(supplier, merger, StringBuilder::toString, NO_CHARACTERISTICS);
1✔
491
        }
492
    }
493

494
    final class CancellableCollectorImpl<T, A, R> extends CancellableCollector<T, A, R> {
495
        private final Supplier<A> supplier;
496
        private final BiConsumer<A, T> accumulator;
497
        private final BinaryOperator<A> combiner;
498
        private final Function<A, R> finisher;
499
        private final Predicate<A> finished;
500
        private final Set<Characteristics> characteristics;
501

502
        CancellableCollectorImpl(Supplier<A> supplier, BiConsumer<A, T> accumulator, BinaryOperator<A> combiner,
503
                                 Function<A, R> finisher, Predicate<A> finished,
504
                                 Set<java.util.stream.Collector.Characteristics> characteristics) {
1✔
505
            this.supplier = supplier;
1✔
506
            this.accumulator = accumulator;
1✔
507
            this.combiner = combiner;
1✔
508
            this.finisher = finisher;
1✔
509
            this.finished = finished;
1✔
510
            this.characteristics = characteristics;
1✔
511
        }
1✔
512

513
        @Override
514
        public Supplier<A> supplier() {
515
            return supplier;
1✔
516
        }
517

518
        @Override
519
        public BiConsumer<A, T> accumulator() {
520
            return accumulator;
1✔
521
        }
522

523
        @Override
524
        public BinaryOperator<A> combiner() {
525
            return combiner;
1✔
526
        }
527

528
        @Override
529
        public Function<A, R> finisher() {
530
            return finisher;
1✔
531
        }
532

533
        @Override
534
        public Set<Characteristics> characteristics() {
535
            return characteristics;
1✔
536
        }
537

538
        @Override
539
        Predicate<A> finished() {
540
            return finished;
1✔
541
        }
542
    }
543

544
    final class IntCollectorImpl<A, R> extends BaseCollector<Integer, A, R> implements IntCollector<A, R> {
545
        private final ObjIntConsumer<A> intAccumulator;
546

547
        IntCollectorImpl(Supplier<A> supplier, ObjIntConsumer<A> intAccumulator, BiConsumer<A, A> merger,
548
                         Function<A, R> finisher, Set<Characteristics> characteristics) {
549
            super(supplier, merger, finisher, characteristics);
1✔
550
            this.intAccumulator = intAccumulator;
1✔
551
        }
1✔
552

553
        @Override
554
        public ObjIntConsumer<A> intAccumulator() {
555
            return intAccumulator;
1✔
556
        }
557
    }
558

559
    final class LongCollectorImpl<A, R> extends BaseCollector<Long, A, R> implements LongCollector<A, R> {
560
        private final ObjLongConsumer<A> longAccumulator;
561

562
        LongCollectorImpl(Supplier<A> supplier, ObjLongConsumer<A> longAccumulator, BiConsumer<A, A> merger,
563
                          Function<A, R> finisher, Set<Characteristics> characteristics) {
564
            super(supplier, merger, finisher, characteristics);
1✔
565
            this.longAccumulator = longAccumulator;
1✔
566
        }
1✔
567

568
        @Override
569
        public ObjLongConsumer<A> longAccumulator() {
570
            return longAccumulator;
1✔
571
        }
572
    }
573

574
    final class DoubleCollectorImpl<A, R> extends BaseCollector<Double, A, R> implements DoubleCollector<A, R> {
575
        private final ObjDoubleConsumer<A> doubleAccumulator;
576

577
        DoubleCollectorImpl(Supplier<A> supplier, ObjDoubleConsumer<A> doubleAccumulator,
578
                            BiConsumer<A, A> merger, Function<A, R> finisher, Set<Characteristics> characteristics) {
579
            super(supplier, merger, finisher, characteristics);
1✔
580
            this.doubleAccumulator = doubleAccumulator;
1✔
581
        }
1✔
582

583
        @Override
584
        public ObjDoubleConsumer<A> doubleAccumulator() {
585
            return doubleAccumulator;
1✔
586
        }
587
    }
588

589
    class Box<A> implements Consumer<A> {
590
        A a;
591
        
592
        Box() {
1✔
593
        }
1✔
594
        
595
        Box(A obj) {
1✔
596
            this.a = obj;
1✔
597
        }
1✔
598

599
        @Override
600
        public void accept(A a) {
601
            this.a = a;
1✔
602
        }
1✔
603

604
        static <A, R> PartialCollector<Box<A>, R> partialCollector(Collector<?, A, R> c) {
605
            Supplier<A> supplier = c.supplier();
1✔
606
            BinaryOperator<A> combiner = c.combiner();
1✔
607
            Function<A, R> finisher = c.finisher();
1✔
608
            return new PartialCollector<>(() -> new Box<>(supplier.get()), (box1, box2) -> box1.a = combiner.apply(
1✔
609
                box1.a, box2.a), box -> finisher.apply(box.a), NO_CHARACTERISTICS);
1✔
610
        }
611

612
        static <A> Optional<A> asOptional(Box<A> box) {
613
            return box == null ? Optional.empty() : Optional.of(box.a);
1✔
614
        }
615
    }
616

617
    /**
618
     * A box of two elements with special equality semantics: only the second element matters for equality.
619
     * 
620
     * @param <A> type of the first element
621
     * @param <B> type of the second element
622
     */
623
    final class PairBox<A, B> extends Box<A> {
624
        B b;
625

626
        PairBox(A a, B b) {
627
            super(a);
1✔
628
            this.b = b;
1✔
629
        }
1✔
630

631
        static <T> PairBox<T, T> single(T a) {
632
            return new PairBox<>(a, a);
1✔
633
        }
634

635
        @Override
636
        public int hashCode() {
637
            return Objects.hashCode(b);
1✔
638
        }
639

640
        @Override
641
        public boolean equals(Object obj) {
642
            return obj != null && obj.getClass() == PairBox.class && Objects.equals(b, ((PairBox<?, ?>) obj).b);
1✔
643
        }
644
    }
645

646
    final class ObjIntBox<A> extends Box<A> implements Entry<Integer, A> {
647
        int b;
648

649
        ObjIntBox(@Nullable A a, int b) {
650
            super(a);
1✔
651
            this.b = b;
1✔
652
        }
1✔
653

654
        @Override
655
        public Integer getKey() {
656
            return b;
1✔
657
        }
658

659
        @Override
660
        public A getValue() {
661
            return a;
1✔
662
        }
663

664
        @Override
665
        public A setValue(A value) {
666
            throw new UnsupportedOperationException();
1✔
667
        }
668

669
        @Override
670
        public int hashCode() {
671
            return Integer.hashCode(b) ^ (a == null ? 0 : a.hashCode());
1✔
672
        }
673

674
        @Override
675
        public boolean equals(Object o) {
676
            if (!(o instanceof Map.Entry))
1✔
677
                return false;
1✔
678
            Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
1✔
679
            return getKey().equals(e.getKey()) && Objects.equals(a, e.getValue());
1✔
680
        }
681

682
        @Override
683
        public String toString() {
684
            return b + "=" + a;
1✔
685
        }
686
    }
687

688
    final class ObjLongBox<A> extends Box<A> implements Entry<A, Long> {
689
        long b;
690

691
        ObjLongBox(A a, long b) {
692
            super(a);
1✔
693
            this.b = b;
1✔
694
        }
1✔
695

696
        @Override
697
        public A getKey() {
698
            return a;
1✔
699
        }
700

701
        @Override
702
        public Long getValue() {
703
            return b;
1✔
704
        }
705

706
        @Override
707
        public Long setValue(Long value) {
708
            throw new UnsupportedOperationException();
1✔
709
        }
710

711
        @Override
712
        public int hashCode() {
713
            return Long.hashCode(b) ^ (a == null ? 0 : a.hashCode());
1✔
714
        }
715

716
        @Override
717
        public boolean equals(Object o) {
718
            if (!(o instanceof Map.Entry))
1✔
719
                return false;
1✔
720
            Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
1✔
721
            return getValue().equals(e.getValue()) && Objects.equals(a, e.getKey());
1✔
722
        }
723

724
        @Override
725
        public String toString() {
726
            return a + "=" + b;
1✔
727
        }
728
    }
729

730
    final class ObjDoubleBox<A> extends Box<A> {
731
        double b;
732

733
        ObjDoubleBox(A a, double b) {
734
            super(a);
1✔
735
            this.b = b;
1✔
736
        }
1✔
737
    }
738

739
    final class PrimitiveBox {
1✔
740
        int i;
741
        double d;
742
        long l;
743
        boolean b;
744

745
        OptionalInt asInt() {
746
            return b ? OptionalInt.of(i) : OptionalInt.empty();
1✔
747
        }
748

749
        OptionalLong asLong() {
750
            return b ? OptionalLong.of(l) : OptionalLong.empty();
1✔
751
        }
752

753
        OptionalDouble asDouble() {
754
            return b ? OptionalDouble.of(d) : OptionalDouble.empty();
1✔
755
        }
756

757
        static final BiConsumer<PrimitiveBox, PrimitiveBox> MAX_LONG = (box1, box2) -> {
1✔
758
            if (box2.b && (!box1.b || box1.l < box2.l)) {
1✔
759
                box1.from(box2);
1✔
760
            }
761
        };
1✔
762

763
        static final BiConsumer<PrimitiveBox, PrimitiveBox> MIN_LONG = (box1, box2) -> {
1✔
764
            if (box2.b && (!box1.b || box1.l > box2.l)) {
1✔
765
                box1.from(box2);
1✔
766
            }
767
        };
1✔
768

769
        static final BiConsumer<PrimitiveBox, PrimitiveBox> MAX_INT = (box1, box2) -> {
1✔
770
            if (box2.b && (!box1.b || box1.i < box2.i)) {
1✔
771
                box1.from(box2);
1✔
772
            }
773
        };
1✔
774

775
        static final BiConsumer<PrimitiveBox, PrimitiveBox> MIN_INT = (box1, box2) -> {
1✔
776
            if (box2.b && (!box1.b || box1.i > box2.i)) {
1✔
777
                box1.from(box2);
1✔
778
            }
779
        };
1✔
780

781
        static final BiConsumer<PrimitiveBox, PrimitiveBox> MAX_DOUBLE = (box1, box2) -> {
1✔
782
            if (box2.b && (!box1.b || Double.compare(box1.d, box2.d) < 0)) {
1✔
783
                box1.from(box2);
1✔
784
            }
785
        };
1✔
786

787
        static final BiConsumer<PrimitiveBox, PrimitiveBox> MIN_DOUBLE = (box1, box2) -> {
1✔
788
            if (box2.b && (!box1.b || Double.compare(box1.d, box2.d) > 0)) {
1✔
789
                box1.from(box2);
1✔
790
            }
791
        };
1✔
792

793
        public void from(PrimitiveBox box) {
794
            b = box.b;
1✔
795
            i = box.i;
1✔
796
            d = box.d;
1✔
797
            l = box.l;
1✔
798
        }
1✔
799
    }
800

801
    final class AverageLong {
1✔
802
        long hi, lo, cnt;
803

804
        public void accept(long val) {
805
            cnt++;
1✔
806
            int cmp = Long.compareUnsigned(lo, lo += val);
1✔
807
            if (val > 0) {
1✔
808
                if (cmp > 0)
1✔
809
                    hi++;
1✔
810
            } else if (cmp < 0)
1✔
811
                hi--;
1✔
812
        }
1✔
813

814
        public AverageLong combine(AverageLong other) {
815
            cnt += other.cnt;
1✔
816
            hi += other.hi;
1✔
817
            if (Long.compareUnsigned(lo, lo += other.lo) > 0) {
1✔
818
                hi++;
1✔
819
            }
820
            return this;
1✔
821
        }
822

823
        public OptionalDouble result() {
824
            if (cnt == 0)
1✔
825
                return OptionalDouble.empty();
1✔
826
            return OptionalDouble.of(((double) (hi + (lo < 0 ? 1 : 0)) / cnt) * 0x1.0p64 + ((double) lo) / cnt);
1✔
827
        }
828
    }
829

830
    @SuppressWarnings("serial")
831
    class CancelException extends Error {
832
        CancelException() {
833
            // Calling this constructor makes the Exception construction much
834
            // faster (like 0.3us vs 1.7us)
835
            super(null, null, false, false);
1✔
836
        }
1✔
837
    }
838

839
    class ArrayCollection extends AbstractCollection<Object> {
840
        private final Object[] arr;
841

842
        ArrayCollection(Object[] arr) {
1✔
843
            this.arr = arr;
1✔
844
        }
1✔
845

846
        @Override
847
        public Iterator<Object> iterator() {
848
            return Arrays.asList(arr).iterator();
1✔
849
        }
850

851
        @Override
852
        public int size() {
853
            return arr.length;
1✔
854
        }
855

856
        @Override
857
        public Object[] toArray() {
858
            // intentional contract violation here:
859
            // this way new ArrayList(new ArrayCollection(arr)) will not copy
860
            // array at all
861
            return arr;
1✔
862
        }
863
    }
864

865
    /**
866
     * A spliterator which may perform tail-stream optimization
867
     *
868
     * @param <T> the type of elements returned by this spliterator
869
     */
870
    interface TailSpliterator<T> extends Spliterator<T> {
871
        /**
872
         * Either advances by one element feeding it to consumer and returns
873
         * this or returns tail spliterator (this spliterator becomes invalid
874
         * and tail must be used instead) or returns null if traversal finished.
875
         * 
876
         * @param action to feed the next element into
877
         * @return tail spliterator, this or null
878
         */
879
        Spliterator<T> tryAdvanceOrTail(Consumer<? super T> action);
880

881
        /**
882
         * Traverses this spliterator and returns null if traversal is completed
883
         * or tail spliterator if it must be used for further traversal.
884
         * 
885
         * @param action to feed the elements into
886
         * @return tail spliterator or null (never returns this)
887
         */
888
        Spliterator<T> forEachOrTail(Consumer<? super T> action);
889

890
        static <T> Spliterator<T> tryAdvanceWithTail(Spliterator<T> target, Consumer<? super T> action) {
891
            while (true) {
892
                if (target instanceof TailSpliterator) {
1✔
893
                    Spliterator<T> spltr = ((TailSpliterator<T>) target).tryAdvanceOrTail(action);
1✔
894
                    if (spltr == null || spltr == target)
1✔
895
                        return spltr;
1✔
896
                    target = spltr;
1✔
897
                } else {
1✔
898
                    return target.tryAdvance(action) ? target : null;
1✔
899
                }
900
            }
901
        }
902

903
        static <T> void forEachWithTail(Spliterator<T> target, Consumer<? super T> action) {
904
            while (true) {
905
                if (target instanceof TailSpliterator) {
1✔
906
                    Spliterator<T> spltr = ((TailSpliterator<T>) target).forEachOrTail(action);
1✔
907
                    if (spltr == null)
1✔
908
                        break;
1✔
909
                    target = spltr;
1✔
910
                } else {
1✔
911
                    target.forEachRemaining(action);
1✔
912
                    break;
1✔
913
                }
914
            }
915
        }
1✔
916
    }
917

918
    abstract class CloneableSpliterator<T, S extends CloneableSpliterator<T, ?>> implements Spliterator<T>,
1✔
919
            Cloneable {
920
        @SuppressWarnings("unchecked")
921
        S doClone() {
922
            try {
923
                return (S) this.clone();
1✔
924
            } catch (CloneNotSupportedException e) {
1✔
925
                throw new InternalError();
1✔
926
            }
927
        }
928
    }
929

930
    static ObjIntConsumer<StringBuilder> joinAccumulatorInt(CharSequence delimiter) {
931
        return (sb, i) -> (sb.length() > 0 ? sb.append(delimiter) : sb).append(i);
1✔
932
    }
933

934
    static ObjLongConsumer<StringBuilder> joinAccumulatorLong(CharSequence delimiter) {
935
        return (sb, i) -> (sb.length() > 0 ? sb.append(delimiter) : sb).append(i);
1✔
936
    }
937

938
    static ObjDoubleConsumer<StringBuilder> joinAccumulatorDouble(CharSequence delimiter) {
939
        return (sb, i) -> (sb.length() > 0 ? sb.append(delimiter) : sb).append(i);
1✔
940
    }
941

942
    static <T> BinaryOperator<T> selectFirst() {
943
        return (u, v) -> u;
1✔
944
    }
945

946
    static <T> Predicate<T> alwaysTrue() {
947
        return t -> true;
1✔
948
    }
949
    
950
    static int checkLength(int a, int b) {
951
        if (a != b)
1✔
952
            throw new IllegalArgumentException("Length differs: " + a + " != " + b);
1✔
953
        return a;
1✔
954
    }
955

956
    static void rangeCheck(int arrayLength, int startInclusive, int endExclusive) {
957
        if (startInclusive > endExclusive) {
1✔
958
            throw new ArrayIndexOutOfBoundsException("startInclusive(" + startInclusive + ") > endExclusive("
1✔
959
                + endExclusive + ")");
960
        }
961
        if (startInclusive < 0) {
1✔
962
            throw new ArrayIndexOutOfBoundsException(startInclusive);
1✔
963
        }
964
        if (endExclusive > arrayLength) {
1✔
965
            throw new ArrayIndexOutOfBoundsException(endExclusive);
1✔
966
        }
967
    }
1✔
968

969
    @SuppressWarnings("unchecked")
970
    static <A> Predicate<A> finished(Collector<?, A, ?> collector) {
971
        if (collector instanceof CancellableCollector)
1✔
972
            return ((CancellableCollector<?, A, ?>) collector).finished();
1✔
973
        return null;
1✔
974
    }
975

976
    @SuppressWarnings("unchecked")
977
    static <T> T none() {
978
        return (T) NONE;
1✔
979
    }
980

981
    static <T> int drainTo(T[] array, Spliterator<T> spliterator) {
982
        Box<T> box = new Box<>();
1✔
983
        int index = 0;
1✔
984
        while (index < array.length && spliterator.tryAdvance(box)) {
1✔
985
            array[index++] = box.a;
1✔
986
        }
987
        return index;
1✔
988
    }
989

990
    static int intSize(Spliterator<?> spliterator) {
991
        long size = spliterator.getExactSizeIfKnown();
1✔
992
        if (size < -1) {
1✔
993
            throw new IllegalArgumentException("Spliterator violates its contract: getExactSizeIfKnown() = " + size);
1✔
994
        }
995
        if (size > Integer.MAX_VALUE) {
1✔
996
            throw new OutOfMemoryError("Stream size exceeds Integer.MAX_VALUE: " + size);
1✔
997
        }
998
        return (int) size;
1✔
999
    }
1000
}
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