Skip to content

Package: Pair$Factory

Pair$Factory

nameinstructionbranchcomplexitylinemethod
Pair.Factory()
M: 0 C: 9
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
lambda$stream$0(IntFunction, IntUnaryOperator, Object)
M: 0 C: 10
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
stream(Iterable, IntUnaryOperator, IntFunction)
M: 0 C: 10
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%

Coverage

1: /*
2: * *********************************************************************************************************************
3: *
4: * TheseFoolishThings: Miscellaneous utilities
5: * http://tidalwave.it/projects/thesefoolishthings
6: *
7: * Copyright (C) 2009 - 2024 by Tidalwave s.a.s. (http://tidalwave.it)
8: *
9: * *********************************************************************************************************************
10: *
11: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
12: * the License. You may obtain a copy of the License at
13: *
14: * http://www.apache.org/licenses/LICENSE-2.0
15: *
16: * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
17: * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
18: * specific language governing permissions and limitations under the License.
19: *
20: * *********************************************************************************************************************
21: *
22: * git clone https://bitbucket.org/tidalwave/thesefoolishthings-src
23: * git clone https://github.com/tidalwave-it/thesefoolishthings-src
24: *
25: * *********************************************************************************************************************
26: */
27: package it.tidalwave.util;
28:
29: import javax.annotation.Nonnegative;
30: import javax.annotation.Nonnull;
31: import javax.annotation.concurrent.Immutable;
32: import javax.annotation.concurrent.NotThreadSafe;
33: import java.util.Map;
34: import java.util.concurrent.atomic.AtomicInteger;
35: import java.util.function.IntFunction;
36: import java.util.function.IntUnaryOperator;
37: import java.util.stream.Collector;
38: import java.util.stream.Collectors;
39: import java.util.stream.IntStream;
40: import java.util.stream.Stream;
41: import java.util.stream.StreamSupport;
42: import lombok.EqualsAndHashCode;
43: import lombok.Getter;
44: import lombok.RequiredArgsConstructor;
45: import lombok.ToString;
46:
47: /***********************************************************************************************************************
48: *
49: * A value object that contains a pair of values. Some factory methods allow creating pairs out of existing collections
50: * or arrays associating an index.
51: *
52: * @author Fabrizio Giudici
53: * @since 3.2-ALPHA-6
54: * @it.tidalwave.javadoc.draft
55: *
56: **********************************************************************************************************************/
57: @Immutable @RequiredArgsConstructor(staticName = "of") @ToString @EqualsAndHashCode
58: public class Pair<A, B>
59: {
60: /** A base 0 index rebaser. */
61: public static final IntUnaryOperator BASE_0 = i -> i;
62:
63: /** A base 1 index rebaser. */
64: public static final IntUnaryOperator BASE_1 = i -> i + 1;
65:
66: @Getter @Nonnull
67: public final A a;
68:
69: @Getter @Nonnull
70: public final B b;
71:
72: /*******************************************************************************************************************
73: *
74: * Creates a {@link Stream} of {@code Pair}s composed of a given fixed value and another element taken from another
75: * {@link Stream}.
76: *
77: * @param <T> the type of the value
78: * @param <U> the type of the {@code Stream}
79: * @param value the value
80: * @param stream the {@code Stream}
81: * @return the {@code Stream} of {@code Pair}s
82: * @since 3.2-ALPHA-12
83: *
84: ******************************************************************************************************************/
85: @Nonnull
86: public static <T, U> Stream<Pair<T, U>> pairStream (@Nonnull final T value,
87: @Nonnull final Stream<? extends U> stream)
88: {
89: return stream.map(object -> Pair.of(value, object));
90: }
91:
92: /*******************************************************************************************************************
93: *
94: * Creates a {@link Stream} of {@code Pair}s composed of a given fixed value and an integer in the given range.
95: *
96: * @param <T> the type of the value
97: * @param value the value
98: * @param from the first value of the integer {@code Stream} (included)
99: * @param to the last value of the integer {@code Stream} (excluded)
100: * @return the {@code Stream} of {@code Pair}s
101: * @since 3.2-ALPHA-12
102: *
103: ******************************************************************************************************************/
104: @Nonnull
105: public static <T> Stream<Pair<T, Integer>> pairRange (@Nonnull final T value,
106: @Nonnegative final int from,
107: @Nonnegative final int to)
108: {
109: return pairStream(value, IntStream.range(from, to).boxed());
110: }
111:
112: /*******************************************************************************************************************
113: *
114: * Creates a {@link Stream} of {@code Pair}s composed of a given fixed value and an integer in the given range.
115: *
116: * @param <T> the type of the value
117: * @param value the value
118: * @param from the first value of the integer {@code Stream} (included)
119: * @param to the last value of the integer {@code Stream} (included)
120: * @return the {@code Stream} of {@code Pair}s
121: * @since 3.2-ALPHA-12
122: *
123: ******************************************************************************************************************/
124: @Nonnull
125: public static <T> Stream<Pair<T, Integer>> pairRangeClosed (@Nonnull final T value,
126: @Nonnegative final int from,
127: @Nonnegative final int to)
128: {
129: return pairStream(value, IntStream.rangeClosed(from, to).boxed());
130: }
131:
132: /*******************************************************************************************************************
133: *
134: * Returns a {@link Stream} out of the elements in a given array made of {@link Pair}s {@code (index, value)}.
135: *
136: * @param <T> the type of the elements
137: * @param array the array
138: * @return the stream
139: *
140: ******************************************************************************************************************/
141: @Nonnull
142: public static <T> Stream<Pair<Integer, T>> indexedPairStream (@Nonnull final T[] array)
143: {
144: return Pair.indexedPairStream(array, BASE_0);
145: }
146:
147: /*******************************************************************************************************************
148: *
149: * Returns a {@link Stream} out of the elements in the array, made of {@link Pair}s {@code (index, value)}. The
150: * index can be rebased.
151: *
152: * @param <T> the type of the elements
153: * @param array the array
154: * @param rebaser the rebaser of the index (BASE_0, BASE_1 or a similar function)
155: * @return the stream
156: *
157: ******************************************************************************************************************/
158: @Nonnull
159: public static <T> Stream<Pair<Integer, T>> indexedPairStream (@Nonnull final T[] array,
160: @Nonnull final IntUnaryOperator rebaser)
161: {
162: return Pair.indexedPairStream(array, rebaser, i -> i);
163: }
164:
165: /*******************************************************************************************************************
166: *
167: * Returns a {@link Stream} out of the elements in a given array made of {@link Pair}s {@code (index, value)}. The
168: * index is transformed with the given function.
169: *
170: * @param <I> the type of the transformed index
171: * @param <T> the type of the elements
172: * @param array the array
173: * @param indexTransformer the transformer of the index
174: * @return the stream
175: *
176: ******************************************************************************************************************/
177: @Nonnull
178: public static <I, T> Stream<Pair<I, T>> indexedPairStream (@Nonnull final T[] array,
179: @Nonnull final IntFunction<? extends I> indexTransformer)
180: {
181: return Pair.indexedPairStream(array, BASE_0, indexTransformer);
182: }
183:
184: /*******************************************************************************************************************
185: *
186: * Returns a {@link Stream} out of the elements in the array, made of {@link Pair}s {@code (index, value)}. The
187: * index can be rebased and transformed with specific functions.
188: *
189: * @param <T> the type of the elements
190: * @param <I> the type of the transformed index
191: * @param array the array
192: * @param rebaser the rebaser of the index (BASE_0, BASE_1 or a similar function)
193: * @param indexTransformer the transformer of the index
194: * @return the stream
195: *
196: ******************************************************************************************************************/
197: @Nonnull
198: public static <T, I> Stream<Pair<I, T>> indexedPairStream (@Nonnull final T[] array,
199: @Nonnull final IntUnaryOperator rebaser,
200: @Nonnull final IntFunction<? extends I> indexTransformer)
201: {
202: return IntStream.range(0, array.length).mapToObj(i -> of(indexTransformer.apply(rebaser.applyAsInt(i)), array[i]));
203: }
204:
205: /*******************************************************************************************************************
206: *
207: * Returns a {@link Stream} out of the elements in a given {@link Iterable} made of {@link Pair}s {@code (index,
208: * value)}.
209: *
210: * @param <T> the type of the elements
211: * @param iterable the iterable
212: * @return the stream
213: *
214: ******************************************************************************************************************/
215: @Nonnull
216: public static <T> Stream<Pair<Integer, T>> indexedPairStream (@Nonnull final Iterable<? extends T> iterable)
217: {
218: return Pair.indexedPairStream(iterable, BASE_0);
219: }
220:
221: /*******************************************************************************************************************
222: *
223: * Returns a {@link Stream} out of the elements in a given {@link Iterable} made of {@link Pair}s {@code (index,
224: * value)}. The index can be rebased.
225: *
226: * @param <T> the type of the elements
227: * @param iterable the iterable
228: * @param rebaser the rebaser of the index (BASE_0, BASE_1 or a similar function)
229: * @return the stream
230: *
231: ******************************************************************************************************************/
232: @Nonnull
233: public static <T> Stream<Pair<Integer, T>> indexedPairStream (@Nonnull final Iterable<? extends T> iterable,
234: @Nonnull final IntUnaryOperator rebaser)
235: {
236: return Pair.indexedPairStream(iterable, rebaser, i -> i);
237: }
238:
239: /*******************************************************************************************************************
240: *
241: * Returns a {@link Stream} out of the elements in a given {@link Iterable} made of {@link Pair}s {@code (index,
242: * value)}. The index is transformed with the given function.
243: *
244: * @param <I> the type of the transformed index
245: * @param <T> the type of the elements
246: * @param iterable the iterable
247: * @param indexTransformer the transformer of the index
248: * @return the stream
249: *
250: ******************************************************************************************************************/
251: @Nonnull @SuppressWarnings("unchecked")
252: public static <I, T> Stream<Pair<I, T>> indexedPairStream (@Nonnull final Iterable<? extends T> iterable,
253: @Nonnull final IntFunction<? extends I> indexTransformer)
254: {
255: return Pair.indexedPairStream(iterable, BASE_0, indexTransformer);
256: }
257:
258: /*******************************************************************************************************************
259: *
260: * Returns a {@link Stream} out of the elements returned by an iterable, made of {@link Pair}s
261: * {@code (index, value)}. The index is rebased and transformed with specific functions.
262: *
263: * @param <T> the type of the elements
264: * @param <I> the type of the transformed index
265: * @param iterable the iterable
266: * @param rebaser the rebaser of the index (BASE_0, BASE_1 or a similar function)
267: * @param indexTransformer the transformer of the index
268: * @return the stream
269: *
270: ******************************************************************************************************************/
271: @Nonnull @SuppressWarnings("unchecked")
272: public static <I, T> Stream<Pair<I, T>> indexedPairStream (@Nonnull final Iterable<? extends T> iterable,
273: @Nonnull final IntUnaryOperator rebaser,
274: @Nonnull final IntFunction<? extends I> indexTransformer)
275: {
276: return new Factory<I, T>().stream(iterable, rebaser, indexTransformer);
277: }
278:
279: /*******************************************************************************************************************
280: *
281: * Returns a {@link Stream} out of the elements in a given {@link Stream} made of {@link Pair}s {@code (index,
282: * value)}.
283: *
284: * @param <T> the type of the elements
285: * @param stream the stream
286: * @return the stream
287: * @since 3.2-ALPHA-12
288: *
289: ******************************************************************************************************************/
290: @Nonnull @SuppressWarnings("unchecked")
291: public static <T> Stream<Pair<Integer, T>> indexedPairStream (@Nonnull final Stream<? extends T> stream)
292: {
293: return Pair.indexedPairStream(((Stream<T>)stream)::iterator);
294: }
295:
296: /*******************************************************************************************************************
297: *
298: * Returns a {@link Stream} out of the elements in a given {@link Stream} made of {@link Pair}s {@code (index,
299: * value)}. The index can be rebased.
300: *
301: * @param <T> the type of the elements
302: * @param stream the stream
303: * @param rebaser the rebaser of the index (BASE_0, BASE_1 or a similar function)
304: * @return the stream
305: * @since 3.2-ALPHA-12
306: *
307: ******************************************************************************************************************/
308: @Nonnull @SuppressWarnings("unchecked")
309: public static <T> Stream<Pair<Integer, T>> indexedPairStream (@Nonnull final Stream<? extends T> stream,
310: @Nonnull final IntUnaryOperator rebaser)
311: {
312: return Pair.indexedPairStream(((Stream<T>)stream)::iterator, rebaser);
313: }
314:
315: /*******************************************************************************************************************
316: *
317: * Returns a {@link Stream} out of the elements in a given {@link Stream} made of {@link Pair}s {@code (index,
318: * value)}. The index is transformed with the given function.
319: *
320: * @param <I> the type of the transformed index
321: * @param <T> the type of the elements
322: * @param stream the stream
323: * @param indexTransformer the transformer of the index
324: * @return the stream
325: * @since 3.2-ALPHA-12
326: *
327: ******************************************************************************************************************/
328: @SuppressWarnings("unchecked")
329: @Nonnull
330: public static <I, T> Stream<Pair<I, T>> indexedPairStream (@Nonnull final Stream<? extends T> stream,
331: @Nonnull final IntFunction<? extends I> indexTransformer)
332: {
333: return Pair.indexedPairStream(((Stream<T>)stream)::iterator, indexTransformer);
334: }
335:
336: /*******************************************************************************************************************
337: *
338: * Returns a {@link Stream} out of the elements returned by a Stream, made of {@link Pair}s
339: * {@code (index, value)}. The index is rebased and transformed with specific functions.
340: *
341: * @param <T> the type of the elements
342: * @param <I> the type of the transformed index
343: * @param stream the stream
344: * @param rebaser the rebaser of the index (BASE_0, BASE_1 or a similar function)
345: * @param indexTransformer the transformer of the index
346: * @return the stream
347: * @since 3.2-ALPHA-12
348: *
349: ******************************************************************************************************************/
350: @SuppressWarnings("unchecked")
351: @Nonnull
352: public static <I, T> Stream<Pair<I, T>> indexedPairStream (@Nonnull final Stream<? extends T> stream,
353: @Nonnull final IntUnaryOperator rebaser,
354: @Nonnull final IntFunction<? extends I> indexTransformer)
355: {
356: return Pair.indexedPairStream(((Stream<T>)stream)::iterator, rebaser, indexTransformer);
357: }
358:
359: /*******************************************************************************************************************
360: *
361: * Returns a {@link Stream} out of the elements returned by a supplier, made of {@link Pair}s
362: * {@code (index, value)}.
363: *
364: * @param <T> the type of the elements
365: * @param from the first index (included)
366: * @param to the last index (excluded)
367: * @param valueSupplier the supplier of values
368: * @return the stream
369: *
370: ******************************************************************************************************************/
371: @Nonnull
372: public static <T> Stream<Pair<Integer, T>> indexedPairStream (@Nonnegative final int from,
373: @Nonnegative final int to,
374: @Nonnull final IntFunction<? extends T> valueSupplier)
375: {
376: return indexedPairStream(from, to, valueSupplier, BASE_0, i -> i);
377: }
378:
379: /*******************************************************************************************************************
380: *
381: * Returns a {@link Stream} out of the elements returned by a supplier, made of {@link Pair}s
382: * {@code (index, value)}.
383: *
384: * @param <T> the type of the elements
385: * @param from the first index (included)
386: * @param to the last index (excluded)
387: * @param valueSupplier the supplier of values
388: * @param rebaser the rebaser of the index (BASE_0, BASE_1 or a similar function)
389: * @return the stream
390: *
391: ******************************************************************************************************************/
392: @Nonnull
393: public static <T> Stream<Pair<Integer, T>> indexedPairStream (@Nonnegative final int from,
394: @Nonnegative final int to,
395: @Nonnull final IntFunction<? extends T> valueSupplier,
396: @Nonnull final IntUnaryOperator rebaser)
397: {
398: return indexedPairStream(from, to, valueSupplier, rebaser, i -> i);
399: }
400:
401: /*******************************************************************************************************************
402: *
403: * Returns a {@link Stream} out of the elements returned by a supplier, made of {@link Pair}s
404: * {@code (index, value)}. The index can be rebased and transformed with specific functions.
405: *
406: * @param <I> the type of the transformed index
407: * @param <T> the type of the elements
408: * @param from the first index (included)
409: * @param to the last index (excluded)
410: * @param valueSupplier the supplier of values
411: * @param rebaser the rebaser of the index (BASE_0, BASE_1 or a similar function)
412: * @param indexTransformer the transformer of the index
413: * @return the stream
414: *
415: ******************************************************************************************************************/
416: @Nonnull
417: public static <T, I> Stream<Pair<I, T>> indexedPairStream (@Nonnegative final int from,
418: @Nonnegative final int to,
419: @Nonnull final IntFunction<? extends T> valueSupplier,
420: @Nonnull final IntUnaryOperator rebaser,
421: @Nonnull final IntFunction<? extends I> indexTransformer)
422: {
423: return IntStream.range(from, to).mapToObj(i -> Pair.of(indexTransformer.apply(rebaser.applyAsInt(i)),
424: valueSupplier.apply(i)));
425: }
426:
427: /*******************************************************************************************************************
428: *
429: * A {@link Collector} that produces a {@link Map} whose key is field {@code a} and value field {@code b}. Use
430: * with {@link Stream#collect(Collector)}.
431: *
432: * @param <A> the type of the former element of the pair
433: * @param <B> the type of the latter element of the pair
434: * @return the {@code Collector}
435: *
436: ******************************************************************************************************************/
437: @Nonnull
438: public static <A, B> Collector<Pair<A, B>, ?, Map<A, B>> pairsToMap()
439: {
440: return Collectors.toMap(p -> p.a, p -> p.b);
441: }
442:
443: /*******************************************************************************************************************
444: *
445: * Zips two streams into a stream of {@link Pair}s.
446: *
447: * @param streamA the first {@link Stream}
448: * @param streamB the second {@link Stream}
449: * @param <A> the type of elements of the first {@link Stream}
450: * @param <B> the type of elements of the second {@link Stream}
451: * @return the zipped {@link Stream}
452: * @since 3.2-ALPHA-17 (since 3.2-ALPHA-12 was in {@code StreamOperations}
453: *
454: ******************************************************************************************************************/
455: @Nonnull
456: public static <A, B> Stream<Pair<A, B>> zip (@Nonnull final Stream<? extends A> streamA,
457: @Nonnull final Stream<? extends B> streamB)
458: {
459: return StreamUtils.zip(streamA, streamB);
460: }
461:
462: @NotThreadSafe
463: static final class Factory<I, T>
464: {
465: private final AtomicInteger n = new AtomicInteger(0);
466:
467: @Nonnull
468: public Stream<Pair<I, T>> stream (@Nonnull final Iterable<? extends T> iterable,
469: @Nonnull final IntUnaryOperator rebaser,
470: @Nonnull final IntFunction<? extends I> indexFunction)
471: {
472: return StreamSupport.stream(iterable.spliterator(), false)
473: .map(o -> Pair.of(indexFunction.apply(rebaser.applyAsInt(n.getAndIncrement())), o));
474: }
475: }
476: }