1 | package com.pivovarit.gatherers; | |
2 | ||
3 | import java.util.Iterator; | |
4 | import java.util.List; | |
5 | import java.util.Map; | |
6 | import java.util.Objects; | |
7 | import java.util.function.BiFunction; | |
8 | import java.util.function.BiPredicate; | |
9 | import java.util.function.Function; | |
10 | import java.util.stream.Gatherer; | |
11 | import java.util.stream.Stream; | |
12 | ||
13 | /// Contains various [java.util.stream.Gatherer] implementations expanding [java.util.stream.Stream] API functionality | |
14 | public final class MoreGatherers { | |
15 | ||
16 | private MoreGatherers() { | |
17 | } | |
18 | ||
19 | /** | |
20 | * Creates a {@link Gatherer} that gathers the last {@code n} elements. | |
21 | * | |
22 | * @param <T> the type of the input elements | |
23 | * @param n the number of last elements to gather | |
24 | * | |
25 | * @return a {@link Gatherer} that collects the last {@code n} elements | |
26 | */ | |
27 | public static <T> Gatherer<T, ?, T> last(int n) { | |
28 |
1
1. last : replaced return value with null for com/pivovarit/gatherers/MoreGatherers::last → KILLED |
return LastGatherer.size(n); |
29 | } | |
30 | ||
31 | /** | |
32 | * Creates a {@link Gatherer} that gathers every {@code n}-th element. | |
33 | * | |
34 | * @param <T> the type of the input elements | |
35 | * @param n the interval at which elements are gathered | |
36 | * | |
37 | * @return a {@link Gatherer} that samples elements every {@code n}-th element | |
38 | */ | |
39 | public static <T> Gatherer<T, ?, T> sampling(int n) { | |
40 |
1
1. sampling : replaced return value with null for com/pivovarit/gatherers/MoreGatherers::sampling → KILLED |
return new SamplingGatherer<>(n); |
41 | } | |
42 | ||
43 | /** | |
44 | * Creates a {@link Gatherer} that filters elements to ensure that only distinct elements | |
45 | * remain, based on a key extracted by the given {@code keyExtractor}, keeping the last | |
46 | * occurrence of each distinct key. | |
47 | * | |
48 | * @param <T> the type of the input elements | |
49 | * @param <U> the type of the key extracted from the input elements | |
50 | * @param keyExtractor the function used to extract the key for distinguishing elements | |
51 | * | |
52 | * @return a {@link Gatherer} that collects distinct elements by key, keeping the last occurrence | |
53 | */ | |
54 | public static <T, U> Gatherer<T, ?, T> distinctByKeepLast(Function<? super T, ? extends U> keyExtractor) { | |
55 |
1
1. distinctByKeepLast : replaced return value with null for com/pivovarit/gatherers/MoreGatherers::distinctByKeepLast → KILLED |
return new DistinctByKeepLastGatherer<>(keyExtractor); |
56 | } | |
57 | ||
58 | /** | |
59 | * Creates a {@link Gatherer} that filters elements to ensure that only distinct elements | |
60 | * remain, based on a key extracted by the given {@code keyExtractor}, keeping the first | |
61 | * occurrence of each distinct key. | |
62 | * | |
63 | * @param <T> the type of the input elements | |
64 | * @param <U> the type of the key extracted from the input elements | |
65 | * @param keyExtractor the function used to extract the key for distinguishing elements | |
66 | * | |
67 | * @return a {@link Gatherer} that collects distinct elements by key, keeping the first occurrence | |
68 | */ | |
69 | public static <T, U> Gatherer<T, ?, T> distinctBy(Function<? super T, ? extends U> keyExtractor) { | |
70 |
1
1. distinctBy : replaced return value with null for com/pivovarit/gatherers/MoreGatherers::distinctBy → KILLED |
return new DistinctByGatherer<>(keyExtractor); |
71 | } | |
72 | ||
73 | /** | |
74 | * Creates a {@link Gatherer} that gathers distinct consecutive elements. | |
75 | * Elements are considered distinct if they are different from the previously gathered element. | |
76 | * | |
77 | * @param <T> the type of the input elements | |
78 | * | |
79 | * @return a {@link Gatherer} that collects distinct consecutive elements | |
80 | */ | |
81 | public static <T> Gatherer<T, ?, T> distinctUntilChanged() { | |
82 |
1
1. distinctUntilChanged : replaced return value with null for com/pivovarit/gatherers/MoreGatherers::distinctUntilChanged → KILLED |
return distinctUntilChanged(Function.identity()); |
83 | } | |
84 | ||
85 | /** | |
86 | * Creates a {@link Gatherer} that gathers distinct consecutive elements | |
87 | * based on a key extracted by the given {@code keyExtractor}. | |
88 | * Elements are considered distinct if the extracted key is different from the previous key. | |
89 | * | |
90 | * @param <T> the type of the input elements | |
91 | * @param <U> the type of the key extracted from the input elements | |
92 | * @param keyExtractor the function used to extract the key for distinguishing elements | |
93 | * | |
94 | * @return a {@link Gatherer} that collects distinct consecutive elements by key | |
95 | */ | |
96 | public static <T, U> Gatherer<T, ?, T> distinctUntilChanged(Function<? super T, ? extends U> keyExtractor) { | |
97 | Objects.requireNonNull(keyExtractor, "keyExtractor can't be null"); | |
98 |
1
1. distinctUntilChanged : replaced return value with null for com/pivovarit/gatherers/MoreGatherers::distinctUntilChanged → KILLED |
return new DistinctUntilChangedGatherer<>(keyExtractor); |
99 | } | |
100 | ||
101 | /** | |
102 | * Creates a {@link Gatherer} that zips elements of type {@code T1} with elements from | |
103 | * another {@link Stream} of type {@code T2}. The resulting pair is returned as a {@link Map.Entry}. | |
104 | * | |
105 | * @param <T1> the type of the first stream elements | |
106 | * @param <T2> the type of the second stream elements | |
107 | * @param other the other stream to zip with | |
108 | * | |
109 | * @return a {@link Gatherer} that pairs elements from the two streams | |
110 | */ | |
111 | public static <T1, T2> Gatherer<T1, ?, Map.Entry<T1, T2>> zip(Stream<T2> other) { | |
112 | Objects.requireNonNull(other, "other can't be null"); | |
113 |
1
1. zip : replaced return value with null for com/pivovarit/gatherers/MoreGatherers::zip → KILLED |
return zip(other.iterator()); |
114 | } | |
115 | ||
116 | /** | |
117 | * Creates a {@link Gatherer} that zips elements of type {@code T1} with elements from | |
118 | * another {@link Stream} of type {@code T2}, and combines them using the provided {@code mapper}. | |
119 | * | |
120 | * @param <T1> the type of the first stream elements | |
121 | * @param <T2> the type of the second stream elements | |
122 | * @param <R> the type of the result produced by the {@code mapper} | |
123 | * @param other the other stream to zip with | |
124 | * @param mapper the function that combines elements from both streams | |
125 | * | |
126 | * @return a {@link Gatherer} that pairs elements from the two streams using the {@code mapper} | |
127 | */ | |
128 | public static <T1, T2, R> Gatherer<T1, ?, R> zip(Stream<T2> other, BiFunction<? super T1, ? super T2, ? extends R> mapper) { | |
129 | Objects.requireNonNull(other, "other can't be null"); | |
130 |
1
1. zip : replaced return value with null for com/pivovarit/gatherers/MoreGatherers::zip → KILLED |
return zip(other.iterator(), mapper); |
131 | } | |
132 | ||
133 | /** | |
134 | * Creates a {@link Gatherer} that zips elements of type {@code T1} with elements from | |
135 | * another {@link Iterable} of type {@code T2}. The resulting pair is returned as a {@link Map.Entry}. | |
136 | * | |
137 | * @param <T1> the type of the first iterable elements | |
138 | * @param <T2> the type of the second iterable elements | |
139 | * @param other the other iterable to zip with | |
140 | * | |
141 | * @return a {@link Gatherer} that pairs elements from the two iterables | |
142 | */ | |
143 | public static <T1, T2> Gatherer<T1, ?, Map.Entry<T1, T2>> zipWithIterable(Iterable<T2> other) { | |
144 | Objects.requireNonNull(other, "other can't be null"); | |
145 |
1
1. zipWithIterable : replaced return value with null for com/pivovarit/gatherers/MoreGatherers::zipWithIterable → KILLED |
return zip(other.iterator()); |
146 | } | |
147 | ||
148 | /** | |
149 | * Creates a {@link Gatherer} that zips elements of type {@code T1} with elements from | |
150 | * another {@link Iterable} of type {@code T2}, and combines them using the provided {@code mapper}. | |
151 | * | |
152 | * @param <T1> the type of the first iterable elements | |
153 | * @param <T2> the type of the second iterable elements | |
154 | * @param <R> the type of the result produced by the {@code mapper} | |
155 | * @param other the other iterable to zip with | |
156 | * @param mapper the function that combines elements from both iterables | |
157 | * | |
158 | * @return a {@link Gatherer} that pairs elements from the two iterables using the {@code mapper} | |
159 | */ | |
160 | public static <T1, T2, R> Gatherer<T1, ?, R> zipWithIterable(Iterable<T2> other, BiFunction<? super T1, ? super T2, ? extends R> mapper) { | |
161 | Objects.requireNonNull(other, "other can't be null"); | |
162 | Objects.requireNonNull(mapper, "mapper can't be null"); | |
163 |
1
1. zipWithIterable : replaced return value with null for com/pivovarit/gatherers/MoreGatherers::zipWithIterable → KILLED |
return zip(other.iterator(), mapper); |
164 | } | |
165 | ||
166 | /** | |
167 | * Creates a {@link Gatherer} that zips elements of type {@code T1} with elements from | |
168 | * another {@link Iterator} of type {@code T2}. The resulting pair is returned as a {@link Map.Entry}. | |
169 | * | |
170 | * @param <T1> the type of the first iterator elements | |
171 | * @param <T2> the type of the second iterator elements | |
172 | * @param iterator the iterator to zip with | |
173 | * | |
174 | * @return a {@link Gatherer} that pairs elements from the two iterators | |
175 | */ | |
176 | public static <T1, T2> Gatherer<T1, ?, Map.Entry<T1, T2>> zip(Iterator<T2> iterator) { | |
177 |
1
1. zip : replaced return value with null for com/pivovarit/gatherers/MoreGatherers::zip → KILLED |
return zip(iterator, Map::entry); |
178 | } | |
179 | ||
180 | /** | |
181 | * Creates a {@link Gatherer} that zips elements of type {@code T1} with elements from | |
182 | * another {@link Iterator} of type {@code T2}, and combines them using the provided {@code mapper}. | |
183 | * | |
184 | * @param <T1> the type of the first iterator elements | |
185 | * @param <T2> the type of the second iterator elements | |
186 | * @param <R> the type of the result produced by the {@code mapper} | |
187 | * @param iterator the iterator to zip with | |
188 | * @param mapper the function that combines elements from both iterators | |
189 | * | |
190 | * @return a {@link Gatherer} that pairs elements from the two iterators using the {@code mapper} | |
191 | */ | |
192 | public static <T1, T2, R> Gatherer<T1, ?, R> zip(Iterator<T2> iterator, BiFunction<? super T1, ? super T2, ? extends R> mapper) { | |
193 |
1
1. zip : replaced return value with null for com/pivovarit/gatherers/MoreGatherers::zip → KILLED |
return new ZipIteratorGatherer<>(iterator, mapper); |
194 | } | |
195 | ||
196 | /** | |
197 | * Creates a {@link Gatherer} that zips elements with their corresponding index, | |
198 | * using the given {@code mapper} to produce the final result. | |
199 | * | |
200 | * @param <T> the type of the input elements | |
201 | * @param <R> the type of the result produced by the {@code mapper} | |
202 | * @param mapper the function that combines an index and an element to produce the result | |
203 | * | |
204 | * @return a {@link Gatherer} that pairs elements with their corresponding index using the {@code mapper} | |
205 | */ | |
206 | public static <T, R> Gatherer<T, ?, R> zipWithIndex(BiFunction<Long, ? super T, ? extends R> mapper) { | |
207 |
1
1. zipWithIndex : replaced return value with null for com/pivovarit/gatherers/MoreGatherers::zipWithIndex → KILLED |
return new ZipWithIndexMappingGatherer<>(mapper); |
208 | } | |
209 | ||
210 | /** | |
211 | * Creates a {@link Gatherer} that zips elements with their corresponding index, | |
212 | * producing a {@link Map.Entry} where the key is the index and the value is the element. | |
213 | * | |
214 | * @param <T> the type of the input elements | |
215 | * | |
216 | * @return a {@link Gatherer} that pairs elements with their corresponding index | |
217 | */ | |
218 | public static <T> Gatherer<T, ?, Map.Entry<T, Long>> zipWithIndex() { | |
219 |
1
1. zipWithIndex : replaced return value with null for com/pivovarit/gatherers/MoreGatherers::zipWithIndex → KILLED |
return new ZipWithIndexGatherer<>(); |
220 | } | |
221 | ||
222 | /** | |
223 | * Creates a {@link Gatherer} that collects elements into sliding windows of a specified size. | |
224 | * Each window captures a subset of elements from the input, and windows slide by a specified step. | |
225 | * <p> | |
226 | * This {@link Gatherer} extends {@link java.util.stream.Gatherers#windowSliding(int)} by allowing to customize the step | |
227 | * | |
228 | * <p>For example, if the window size is 3 and the step is 1, the gatherer will collect | |
229 | * windows of size 3, sliding by 1 element at a time. This means each subsequent window overlaps | |
230 | * with the previous one by two elements.</p> | |
231 | * | |
232 | * <p>Common use cases include moving averages, trend analysis, and any scenario requiring | |
233 | * overlapping or rolling window operations on a list of elements.</p> | |
234 | * | |
235 | * @param <T> the type of elements in the input and output list | |
236 | * @param windowSize the size of each window (must be a positive integer) | |
237 | * @param step the number of elements to slide the window by (must be a positive integer) | |
238 | * | |
239 | * @return a {@link Gatherer} that collects elements into sliding windows | |
240 | * | |
241 | * @throws IllegalArgumentException if {@code windowSize} is less than one or {@code step} is less than zero, or greater than {@code windowSize} | |
242 | */ | |
243 | public static <T> Gatherer<T, ?, List<T>> windowSliding(int windowSize, int step) { | |
244 |
1
1. windowSliding : replaced return value with null for com/pivovarit/gatherers/MoreGatherers::windowSliding → KILLED |
return new WindowSlidingGatherer<>(windowSize, step); |
245 | } | |
246 | ||
247 | /** | |
248 | * Creates a {@link Gatherer} that filters elements based on their index and value using a given {@link BiPredicate}. | |
249 | * The provided {@code BiPredicate} is applied to each element of the source, along with its corresponding index | |
250 | * (starting from 0). Only the elements that satisfy the predicate (i.e., for which the predicate returns {@code true}) | |
251 | * are retained. | |
252 | * <p> | |
253 | * The same result can be achieved by using {@code zipWithIndex()}, {@code filter()}, and {@code map()}. | |
254 | * However, this method is significantly faster because it avoids the intermediate steps and directly filters | |
255 | * elements based on their index. | |
256 | * | |
257 | * @param <T> the type of elements to be filtered | |
258 | * @param predicate a {@link BiPredicate} that takes the index and element as input, and returns {@code true} to retain | |
259 | * the element, or {@code false} to exclude it | |
260 | * | |
261 | * @return a {@link Gatherer} that applies the given filter based on element index and value | |
262 | */ | |
263 | public static <T> Gatherer<T, ?, T> byIndex(BiPredicate<Long, ? super T> predicate) { | |
264 |
1
1. byIndex : replaced return value with null for com/pivovarit/gatherers/MoreGatherers::byIndex → KILLED |
return new FilterByIndexGatherer<>(predicate); |
265 | } | |
266 | } | |
Mutations | ||
28 |
1.1 |
|
40 |
1.1 |
|
55 |
1.1 |
|
70 |
1.1 |
|
82 |
1.1 |
|
98 |
1.1 |
|
113 |
1.1 |
|
130 |
1.1 |
|
145 |
1.1 |
|
163 |
1.1 |
|
177 |
1.1 |
|
193 |
1.1 |
|
207 |
1.1 |
|
219 |
1.1 |
|
244 |
1.1 |
|
264 |
1.1 |