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

SpiNNakerManchester / JavaSpiNNaker / 6233274834

19 Sep 2023 08:46AM UTC coverage: 36.409% (-0.6%) from 36.982%
6233274834

Pull #658

github

dkfellows
Merge branch 'master' into java-17
Pull Request #658: Update Java version to 17

1656 of 1656 new or added lines in 260 files covered. (100.0%)

8373 of 22997 relevant lines covered (36.41%)

0.36 hits per line

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

0.0
/SpiNNaker-utils/src/main/java/uk/ac/manchester/spinnaker/utils/CollectionUtils.java
1
/*
2
 * Copyright (c) 2022 The University of Manchester
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
 *     https://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 uk.ac.manchester.spinnaker.utils;
17

18
import static java.lang.Math.min;
19
import static java.util.Arrays.stream;
20
import static java.util.Collections.unmodifiableCollection;
21
import static java.util.Collections.unmodifiableList;
22
import static java.util.Collections.unmodifiableMap;
23
import static java.util.Collections.unmodifiableSet;
24
import static java.util.EnumSet.noneOf;
25
import static java.util.Objects.isNull;
26
import static java.util.stream.Collectors.toCollection;
27
import static java.util.stream.Collectors.toUnmodifiableList;
28
import static java.util.stream.Collectors.toUnmodifiableMap;
29
import static uk.ac.manchester.spinnaker.utils.MathUtils.ceildiv;
30

31
import java.util.ArrayList;
32
import java.util.Collection;
33
import java.util.EnumSet;
34
import java.util.LinkedHashMap;
35
import java.util.LinkedHashSet;
36
import java.util.List;
37
import java.util.Map;
38
import java.util.Set;
39
import java.util.function.BiConsumer;
40
import java.util.function.BiFunction;
41
import java.util.function.BinaryOperator;
42
import java.util.function.Function;
43
import java.util.function.IntBinaryOperator;
44
import java.util.function.IntFunction;
45
import java.util.function.Supplier;
46
import java.util.stream.Collector;
47
import java.util.stream.IntStream;
48
import java.util.stream.Stream;
49

50
/**
51
 * Utilities for working with collections. Things that it would be nice if they
52
 * were in Java itself, but which aren't.
53
 *
54
 * @author Donal Fellows
55
 * @see MappableIterable
56
 */
57
public abstract class CollectionUtils {
58
        private CollectionUtils() {
59
        }
60

61
        /**
62
         * The binary and operator ({@code &}) as a function.
63
         */
64
        public static final IntBinaryOperator AND = (a, b) -> a & b;
×
65

66
        /**
67
         * The binary or operator ({@code |}) as a function.
68
         */
69
        public static final IntBinaryOperator OR = (a, b) -> a | b;
×
70

71
        /**
72
         * Create a collector that collects to an {@link EnumSet}.
73
         *
74
         * @param <E>
75
         *            The type of {@code enum} we are collecting.
76
         * @param cls
77
         *            The class of the {@code enum} we are collecting.
78
         * @return The collector.
79
         */
80
        public static <E extends Enum<E>> Collector<E, ?, EnumSet<E>> toEnumSet(
81
                        Class<E> cls) {
82
                return toCollection(() -> noneOf(cls));
×
83
        }
84

85
        /**
86
         * Generate an iterable that covers a range. Only expected to cover the
87
         * range once.
88
         *
89
         * @param startAt
90
         *            What value to start at.
91
         * @param upTo
92
         *            What value to go up to (in steps of +1) but not include.
93
         * @return A one-shot iterable.
94
         */
95
        public static Iterable<Integer> range(int startAt, int upTo) {
96
                return IntStream.range(startAt, upTo)::iterator;
×
97
        }
98

99
        /**
100
         * Generate an iterable that covers a range starting at zero and counting
101
         * up. Only expected to cover the range once.
102
         *
103
         * @param upTo
104
         *            What value to go up to (in steps of +1) but not include.
105
         * @return A one-shot iterable.
106
         */
107
        public static Iterable<Integer> range(int upTo) {
108
                return IntStream.range(0, upTo)::iterator;
×
109
        }
110

111
        /**
112
         * Binary function currier.
113
         *
114
         * @param <T>
115
         *            First argument type.
116
         * @param <U>
117
         *            Second argument type
118
         * @param <V>
119
         *            Return type.
120
         * @param fn
121
         *            Binary function.
122
         * @param arg
123
         *            First argument.
124
         * @return Unary function based on binding the first argument to the binary
125
         *         function.
126
         */
127
        public static <T, U, V> Function<U, V> curry(BiFunction<T, U, V> fn,
128
                        T arg) {
129
                return u -> fn.apply(arg, u);
×
130
        }
131

132
        /**
133
         * Given a list of elements, split it into batches of elements of a given
134
         * size. The final batch might be smaller. Note that this <em>requires</em>
135
         * a list because it uses the {@link List#subList(int, int)} method.
136
         *
137
         * @param <T>
138
         *            The type of the elements of the input list.
139
         * @param batchSize
140
         *            The maximum number of elements in a batch. All but the final
141
         *            batch will have this number of elements; the final batch may
142
         *            have fewer.
143
         * @param input
144
         *            The list to be split into batches.
145
         * @return The batched list. The collections that make up each batch will be
146
         *         unmodifiable, as will the overall collection.
147
         */
148
        public static <T> Collection<Collection<T>> batch(int batchSize,
149
                        List<T> input) {
150
                return IntStream.range(0, ceildiv(input.size(), batchSize))
×
151
                                .map(i -> i * batchSize)
×
152
                                .mapToObj(idx -> unmodifiableCollection(
×
153
                                                input.subList(idx, min(input.size(), idx + batchSize))))
×
154
                                .collect(toUnmodifiableList());
×
155
        }
156

157
        /**
158
         * Like {@link Stream#map(Function)}, but for lists/collections.
159
         *
160
         * @param <T>
161
         *            The type of elements of the input list.
162
         * @param <U>
163
         *            The type of elements of the output list.
164
         * @param list
165
         *            The input list.
166
         * @param fun
167
         *            How to map an element.
168
         * @return The output list. Unmodifiable.
169
         */
170
        @UsedInJavadocOnly(Stream.class)
171
        public static <T, U> List<U> lmap(Collection<T> list, Function<T, U> fun) {
172
                return list.stream().map(fun).collect(toUnmodifiableList());
×
173
        }
174

175
        /**
176
         * Utility for making the backing maps for fast {@code enum}s. These are
177
         * expected to be used mainly to invert the trivial mapping from an
178
         * enumeration member to its {@code value} field, though this is not assumed
179
         * by this code.
180
         *
181
         * @param <E>
182
         *            The type of the {@code enum}.
183
         * @param <K>
184
         *            The type of the value to use as the map key.
185
         * @param enumMembers
186
         *            The values in the {@code enum}, as returned by the
187
         *            {@code values()} method.
188
         * @param valueExtractor
189
         *            How to get the value to use as the map key.
190
         * @return Unmodifiable map from the values to the {@code enum} members.
191
         */
192
        public static <E extends Enum<E>, K> Map<K, E> makeEnumBackingMap(
193
                        E[] enumMembers, Function<E, K> valueExtractor) {
194
                return stream(enumMembers)
×
195
                                .collect(toUnmodifiableMap(valueExtractor, v -> v));
×
196
        }
197

198
        /**
199
         * Makes a read-only copy of a list.
200
         *
201
         * @param <T>
202
         *            The type of elements in the list.
203
         * @param list
204
         *            The list to copy. {@code null} becomes an empty list.
205
         * @return A read-only copy of the list.
206
         */
207
        public static <T> List<T> copy(List<T> list) {
208
                // Don't copyOf; avoid nullability failures
209
                return isNull(list) ? List.of()
×
210
                                : unmodifiableList(new ArrayList<>(list));
×
211
        }
212

213
        /**
214
         * Makes a read-only copy of a set. This will preserve whatever order was in
215
         * the input set.
216
         *
217
         * @param <T>
218
         *            The type of elements in the set.
219
         * @param set
220
         *            The set to copy. {@code null} becomes an empty set.
221
         * @return A read-only copy of the set.
222
         */
223
        public static <T> Set<T> copy(Set<T> set) {
224
                // Don't copyOf; avoid nullability failures
225
                return isNull(set) ? Set.of()
×
226
                                : unmodifiableSet(new LinkedHashSet<>(set));
×
227
        }
228

229
        /**
230
         * Makes a read-only copy of a map. This will preserve whatever order was in
231
         * the input map.
232
         *
233
         * @param <K>
234
         *            The type of keys in the map.
235
         * @param <V>
236
         *            The type of values in the map.
237
         * @param map
238
         *            The map to copy. {@code null} becomes an empty map.
239
         * @return A read-only copy of the map.
240
         */
241
        public static <K, V> Map<K, V> copy(Map<K, V> map) {
242
                // Don't copyOf; avoid nullability failures
243
                return isNull(map) ? Map.of()
×
244
                                : unmodifiableMap(new LinkedHashMap<>(map));
×
245
        }
246

247
        /**
248
         * Create a collector that produces an array from a stream. The order of the
249
         * elements in the array will be the inherent order of the elements in the
250
         * stream.
251
         *
252
         * @param <T>
253
         *            The type of the elements.
254
         * @param generator
255
         *            How to make the array. Typically something like
256
         *            {@code T[]::new}.
257
         * @return A collector.
258
         */
259
        public static <
260
                        T> Collector<T, ?, T[]> collectToArray(IntFunction<T[]> generator) {
261
                return new Collector<T, List<T>, T[]>() {
×
262
                        @Override
263
                        public Supplier<List<T>> supplier() {
264
                                return ArrayList::new;
×
265
                        }
266

267
                        @Override
268
                        public BiConsumer<List<T>, T> accumulator() {
269
                                return List::add;
×
270
                        }
271

272
                        @Override
273
                        public BinaryOperator<List<T>> combiner() {
274
                                return (left, right) -> {
×
275
                                        left.addAll(right);
×
276
                                        return left;
×
277
                                };
278
                        }
279

280
                        @Override
281
                        public Function<List<T>, T[]> finisher() {
282
                                // We know the size right now; use it!
283
                                // Also, we assume that the generator is non-crazy
284
                                return l -> l.toArray(generator.apply(l.size()));
×
285
                        }
286

287
                        @Override
288
                        public Set<Characteristics> characteristics() {
289
                                return Set.of();
×
290
                        }
291
                };
292
        }
293
}
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

© 2026 Coveralls, Inc