Add StreamZipper
This commit is contained in:
parent
2d58712047
commit
fd9a0a2199
3 changed files with 124 additions and 0 deletions
60
src/main/java/net/kemitix/text/fit/StreamZipper.java
Normal file
60
src/main/java/net/kemitix/text/fit/StreamZipper.java
Normal file
|
@ -0,0 +1,60 @@
|
|||
package net.kemitix.text.fit;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.IntFunction;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.lang.Math.min;
|
||||
import static java.util.stream.IntStream.range;
|
||||
|
||||
/**
|
||||
* Utility to zip two {@link Stream}s together.
|
||||
*
|
||||
* @author Paul Campbell (pcampbell@kemitix.net)
|
||||
*/
|
||||
public final class StreamZipper {
|
||||
|
||||
private StreamZipper() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Zip two {@link Stream}s together.
|
||||
*
|
||||
* <p>The resulting stream will contain only as many items as the shortest of the two lists.</p>
|
||||
*
|
||||
* @param a the first List
|
||||
* @param b the second List
|
||||
* @param zipper the function to zip an item from each list
|
||||
* @param <A> the type of the first list
|
||||
* @param <B> the type of the second list
|
||||
* @param <C> the type of the joined items
|
||||
* @return a Stream of the joined items
|
||||
*/
|
||||
public static <A, B, C> Stream<C> zip(
|
||||
final List<A> a,
|
||||
final List<B> b,
|
||||
final BiFunction<A, B, C> zipper
|
||||
) {
|
||||
return range(0, limit(a, b))
|
||||
.mapToObj(tuple(a, b, zipper));
|
||||
}
|
||||
|
||||
private static <A, B> int limit(
|
||||
final List<A> a,
|
||||
final List<B> b
|
||||
) {
|
||||
return min(a.size(), b.size());
|
||||
}
|
||||
|
||||
private static <A, B, C> IntFunction<C> tuple(
|
||||
final List<A> a,
|
||||
final List<B> b,
|
||||
final BiFunction<A, B, C> zipper
|
||||
) {
|
||||
return i -> zipper.apply(a.get(i), b.get(i));
|
||||
}
|
||||
|
||||
}
|
24
src/main/java/net/kemitix/text/fit/Tuple.java
Normal file
24
src/main/java/net/kemitix/text/fit/Tuple.java
Normal file
|
@ -0,0 +1,24 @@
|
|||
package net.kemitix.text.fit;
|
||||
|
||||
public class Tuple<A, B> {
|
||||
|
||||
private final A partA;
|
||||
private final B partB;
|
||||
|
||||
private Tuple(final A partA, final B partB) {
|
||||
this.partA = partA;
|
||||
this.partB = partB;
|
||||
}
|
||||
|
||||
public static <A, B> Tuple<A, B> of(final A a, final B b) {
|
||||
return new Tuple<>(a, b);
|
||||
}
|
||||
|
||||
public A get1() {
|
||||
return partA;
|
||||
}
|
||||
|
||||
public B get2() {
|
||||
return partB;
|
||||
}
|
||||
}
|
40
src/test/java/net/kemitix/text/fit/StreamZipperTest.java
Normal file
40
src/test/java/net/kemitix/text/fit/StreamZipperTest.java
Normal file
|
@ -0,0 +1,40 @@
|
|||
package net.kemitix.text.fit;
|
||||
|
||||
import org.assertj.core.api.WithAssertions;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
class StreamZipperTest implements WithAssertions {
|
||||
|
||||
@Test
|
||||
void privateUtilityConstructor() throws NoSuchMethodException {
|
||||
//given
|
||||
final Constructor<StreamZipper> constructor = StreamZipper.class.getDeclaredConstructor();
|
||||
constructor.setAccessible(true);
|
||||
//then
|
||||
assertThatCode(constructor::newInstance)
|
||||
.hasCauseInstanceOf(UnsupportedOperationException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Pair two lists together")
|
||||
void pairItems() {
|
||||
//when
|
||||
final List<String> strings = Arrays.asList("One", "Two", "Three");
|
||||
final List<Integer> integers = Arrays.asList(3, 2, 1);
|
||||
final List<Tuple<String, Integer>> zipped =
|
||||
StreamZipper.zip(strings, integers, Tuple::of).collect(Collectors.toList());
|
||||
//then
|
||||
assertThat(zipped)
|
||||
.extracting(Tuple::get1)
|
||||
.containsExactlyElementsOf(strings.subList(0, zipped.size()));
|
||||
assertThat(zipped)
|
||||
.extracting(Tuple::get2)
|
||||
.containsExactlyElementsOf(integers.subList(0, zipped.size()));
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue