1 | package com.pivovarit.collectors; | |
2 | ||
3 | import java.util.ArrayList; | |
4 | import java.util.List; | |
5 | import java.util.Spliterator; | |
6 | import java.util.function.Consumer; | |
7 | import java.util.function.Function; | |
8 | import java.util.stream.Stream; | |
9 | ||
10 | import static java.util.stream.Stream.empty; | |
11 | import static java.util.stream.Stream.of; | |
12 | import static java.util.stream.StreamSupport.stream; | |
13 | ||
14 | /** | |
15 | * @author Grzegorz Piwowarek | |
16 | */ | |
17 | final class BatchingSpliterator<T> implements Spliterator<List<T>> { | |
18 | ||
19 | private final List<T> source; | |
20 | private final int maxChunks; | |
21 | ||
22 | private int chunks; | |
23 | private int chunkSize; | |
24 | private int consumed; | |
25 | ||
26 | private BatchingSpliterator(List<T> list, int batches) { | |
27 |
2
1. <init> : changed conditional boundary → SURVIVED 2. <init> : negated conditional → KILLED |
if (batches < 1) { |
28 | throw new IllegalArgumentException("batches can't be lower than one"); | |
29 | } | |
30 | source = list; | |
31 | chunks = batches; | |
32 | maxChunks = Math.min(list.size(), batches); | |
33 |
1
1. <init> : Replaced double division with multiplication → KILLED |
chunkSize = (int) Math.ceil(((double) source.size()) / batches); |
34 | } | |
35 | ||
36 | static <T> Stream<List<T>> partitioned(List<T> list, int numberOfParts) { | |
37 | int size = list.size(); | |
38 | ||
39 |
2
1. partitioned : changed conditional boundary → SURVIVED 2. partitioned : negated conditional → KILLED |
if (size <= numberOfParts) { |
40 |
1
1. partitioned : replaced return value with Stream.empty for com/pivovarit/collectors/BatchingSpliterator::partitioned → KILLED |
return asSingletonListStream(list); |
41 |
1
1. partitioned : negated conditional → KILLED |
} else if (size == 0) { |
42 | return empty(); | |
43 |
1
1. partitioned : negated conditional → KILLED |
} else if (numberOfParts == 1) { |
44 |
1
1. partitioned : replaced return value with Stream.empty for com/pivovarit/collectors/BatchingSpliterator::partitioned → KILLED |
return of(list); |
45 | } else { | |
46 |
1
1. partitioned : replaced return value with Stream.empty for com/pivovarit/collectors/BatchingSpliterator::partitioned → KILLED |
return stream(new BatchingSpliterator<>(list, numberOfParts), false); |
47 | } | |
48 | } | |
49 | ||
50 | private static <T> Stream<List<T>> asSingletonListStream(List<T> list) { | |
51 | Stream.Builder<List<T>> acc = Stream.builder(); | |
52 | for (T t : list) { | |
53 | acc.add(List.of(t)); | |
54 | } | |
55 |
1
1. asSingletonListStream : replaced return value with Stream.empty for com/pivovarit/collectors/BatchingSpliterator::asSingletonListStream → KILLED |
return acc.build(); |
56 | } | |
57 | ||
58 | static <T, R> Function<List<T>, List<R>> batching(Function<T, R> mapper) { | |
59 |
1
1. batching : replaced return value with null for com/pivovarit/collectors/BatchingSpliterator::batching → KILLED |
return batch -> { |
60 | List<R> list = new ArrayList<>(batch.size()); | |
61 | for (T t : batch) { | |
62 | list.add(mapper.apply(t)); | |
63 | } | |
64 |
1
1. lambda$batching$0 : replaced return value with Collections.emptyList for com/pivovarit/collectors/BatchingSpliterator::lambda$batching$0 → KILLED |
return list; |
65 | }; | |
66 | } | |
67 | ||
68 | @Override | |
69 | public boolean tryAdvance(Consumer<? super List<T>> action) { | |
70 |
3
1. tryAdvance : changed conditional boundary → SURVIVED 2. tryAdvance : negated conditional → KILLED 3. tryAdvance : negated conditional → KILLED |
if (consumed < source.size() && chunks != 0) { |
71 |
1
1. tryAdvance : Replaced integer addition with subtraction → KILLED |
List<T> batch = source.subList(consumed, consumed + chunkSize); |
72 |
1
1. tryAdvance : Replaced integer addition with subtraction → KILLED |
consumed += chunkSize; |
73 |
3
1. tryAdvance : Replaced double division with multiplication → KILLED 2. tryAdvance : Replaced integer subtraction with addition → KILLED 3. tryAdvance : Replaced integer subtraction with addition → KILLED |
chunkSize = (int) Math.ceil(((double) (source.size() - consumed)) / --chunks); |
74 |
1
1. tryAdvance : removed call to java/util/function/Consumer::accept → KILLED |
action.accept(batch); |
75 |
1
1. tryAdvance : replaced boolean return with false for com/pivovarit/collectors/BatchingSpliterator::tryAdvance → KILLED |
return true; |
76 | } else { | |
77 |
1
1. tryAdvance : replaced boolean return with true for com/pivovarit/collectors/BatchingSpliterator::tryAdvance → TIMED_OUT |
return false; |
78 | } | |
79 | } | |
80 | ||
81 | @Override | |
82 | public Spliterator<List<T>> trySplit() { | |
83 | return null; | |
84 | } | |
85 | ||
86 | @Override | |
87 | public long estimateSize() { | |
88 |
1
1. estimateSize : replaced long return with 0 for com/pivovarit/collectors/BatchingSpliterator::estimateSize → KILLED |
return maxChunks; |
89 | } | |
90 | ||
91 | @Override | |
92 | public int characteristics() { | |
93 |
1
1. characteristics : replaced int return with 0 for com/pivovarit/collectors/BatchingSpliterator::characteristics → SURVIVED |
return ORDERED | SIZED; |
94 | } | |
95 | } | |
Mutations | ||
27 |
1.1 2.2 |
|
33 |
1.1 |
|
39 |
1.1 2.2 |
|
40 |
1.1 |
|
41 |
1.1 |
|
43 |
1.1 |
|
44 |
1.1 |
|
46 |
1.1 |
|
55 |
1.1 |
|
59 |
1.1 |
|
64 |
1.1 |
|
70 |
1.1 2.2 3.3 |
|
71 |
1.1 |
|
72 |
1.1 |
|
73 |
1.1 2.2 3.3 |
|
74 |
1.1 |
|
75 |
1.1 |
|
77 |
1.1 |
|
88 |
1.1 |
|
93 |
1.1 |