• 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.01
/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 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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

303
    final class BooleanMap<T> extends AbstractMap<Boolean, T> {
304
        T trueValue, falseValue;
305

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

647
        ObjIntBox(A a, int b) {
648
            super(a);
1✔
649
            this.b = b;
1✔
650
        }
1✔
651

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

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

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

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

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

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

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

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

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

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

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

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

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

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

728
    final class ObjDoubleBox<A> extends Box<A> {
729
        double b;
730

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

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

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

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

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

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

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

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

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

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

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

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

799
    final class AverageLong {
1✔
800
        long hi, lo, cnt;
801

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

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

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

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

837
    class ArrayCollection extends AbstractCollection<Object> {
838
        private final Object[] arr;
839

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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