Iterators { public static <T> List<ImmutableIterator<T>> unzip(Iterator<List<T>> zippedIterator) { List<T> firstColumn = zippedIterator.next(); int n = firstColumn.size(); @SuppressWarnings("unchecked") List<ImmutableIterator<List<T>>> aux = tee(concat(of(firstColumn), zippedIterator), n); List<ImmutableIterator<T>> result = new ArrayList<>(n); for (int i = 0; i < n; i++) { int j = i; result.add(j, map(aux.get(j), xs -> j < xs.size() ? xs.get(j) : null)); } return result; } private  Iterators(); static ImmutableIterator<T> of(T... xs); static ImmutableIterator<T> asIterator(Iterable<T> xs); static ImmutableIterator<T> repeat(T x, int n); static InfiniteIterator<T> repeat(T x); static ImmutableIterator<T> empty(); static ImmutableIterator<T> of(T element); static InfiniteIterator<T> generate(Supplier<T> sp); static ImmutableIterator<T> concat(Iterator<T>... ts); static InfiniteIterator<T> cycle(T... xs); static List<T> take(Iterator<T> t, int n); static List<T> takeAll(Iterator<T> t); static ImmutableIterator<T> limit(Iterator<T> t, int n); static ImmutableIterator<T> reverse(List<T> xs); static ImmutableIterator<T> peek(Iterator<T> t, Consumer<? super T> cs); static ImmutableIterator<T> map(Iterator<F> from, Function<? super F, ? extends T> mapper); static ImmutableIterator<T> map(Iterator<T> first,
                                               Iterator<T> second,
                                               BinaryOperator<T> mapper); static T reduce(Iterator<T> t, BinaryOperator<T> acc); static V reduce(Iterator<T> t, BiFunction<V, T, V> acc, V seed); static ImmutableIterator<T> merge(List<Iterator<T>> iterators, boolean weak); static List<ImmutableIterator<T>> tee(Iterator<T> from, int forks); static ImmutableIterator<List<T>> zip(List<Iterator<T>> ts); static ImmutableIterator<List<T>> zip(List<Iterator<T>> ts, boolean weak); static List<ImmutableIterator<T>> unzip(Iterator<List<T>> zippedIterator); static ImmutableIterator<Pair<A, B>> zip(Pair<Iterator<A>, Iterator<B>> iterators, boolean weak); static ImmutableIterator<T> skipDuplicates(Iterator<T> iterator, Function<? super T, ? extends K> key); static ImmutableIterator<T> keepFirst(Iterator<T> iterator, Function<? super T, ? extends K> key); static ImmutableIterator<T> keepLast(Iterator<T> iterator, Function<? super T, ? extends K> key); static ImmutableIterator<T> skipDuplicates(Iterator<T> iterator); static ImmutableIterator<T> keepFirst(Iterator<T> iterator); static ImmutableIterator<T> keepLast(Iterator<T> iterator); static ImmutableIterator<List<T>> groupBy(Iterator<T> iterator, Function<T, V> key); static ImmutableIterator<List<T>> groupBy(Iterator<T> iterator); static boolean weakEquals(Iterator<? extends T> first, Iterator<? extends T> second, int n); static boolean any(Iterator<T> t, Predicate<? super T> p); static boolean any(Iterable<T> xs, Predicate<? super T> p); static boolean all(Iterable<T> xs, Predicate<? super T> p); static boolean all(Iterator<T> t, Predicate<? super T> p); static ImmutableIterator filter(Iterable<T> xs, Predicate<? super T> p); static ImmutableIterator filter(Iterator<T> t, Predicate<? super T> p); static InfiniteIterator<T> unaryGenerator(T v, UnaryOperator<T> f); static InfiniteIterator<T> binaryGenerator(T v, T w, BinaryOperator<T> f);  }
@Test public void testUnzip() { Iterator<Integer> s = repeat(10); Iterator<Integer> t = repeat(20); List<Iterator<Integer>> m = asList(s, t); Iterator<List<Integer>> rs = zip(m); List<ImmutableIterator<Integer>> zs = unzip(rs); BinaryOperator<Integer> acc = (a, b) -> a + b; int sum0 = reduce(limit(zs.get(0), 5), acc); int sum1 = reduce(limit(zs.get(1), 5), acc); assertEquals(50, sum0); assertEquals(100, sum1); Iterator<List<Integer>> cool = unaryGenerator(asList(100, 200, 300), (List<Integer> xs) -> take(map(asIterator(xs), (Integer x) -> x + 1), 3)); zs = unzip(take(cool, 5).iterator()); sum0 = reduce(zs.get(0), acc); sum1 = reduce(zs.get(1), acc); int sum2 = reduce(zs.get(2), acc); assertEquals(510, sum0); assertEquals(1010, sum1); assertEquals(1510, sum2); List<Integer> a = asList(1, 2, 3); List<Integer> b = asList(1, 2, 3, 4); List<Integer> c = asList(1, 2); List<Integer> d = asList(1); List<Integer> e = asList(); Iterator<List<Integer>> ts = of(a, b, c, d, e); List<Integer> y; BinaryOperator<Integer> wadd = weakBinaryOperator((u, v) -> u + v); List<ImmutableIterator<Integer>> us = unzip(ts); assertEquals((Integer) 4, reduce(us.get(0), wadd)); assertEquals((Integer) 6, reduce(us.get(1), wadd)); assertEquals((Integer) 6, reduce(us.get(2), wadd)); }