Add StreamZipper

This commit is contained in:
Paul Campbell 2020-05-22 20:51:42 +01:00
parent 2d58712047
commit fd9a0a2199
3 changed files with 124 additions and 0 deletions

View 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));
}
}

View 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;
}
}

View 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()));
}
}