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