Iterate two Java-8-Streams together [duplicate]

I'd like to iterate two Java-8-Streams together, so that I have in each iteration-step two arguments. Something like that, where somefunction produces something like Stream<Pair<A,B>>.

Stream<A> as;
Stream<B> bs;
somefunction (as, bs)
  .forEach ((a, b) -> foo (a, b));
// or something like
somefunction (as, bs)
  .forEach ((Pair<A, B> abs) -> foo (abs.left (), abs.right ()));

I want to know, if Java provides something like that, although there is no Pair in Java :-( If there is no API-Function like that, is there another way of iterating two streams simultaniously?


static <A, B> Stream<Pair<A, B>> zip(Stream<A> as, Stream<B> bs)
{
    Iterator<A> i=as.iterator();
    return bs.filter(x->i.hasNext()).map(b->new Pair<>(i.next(), b));
}

This does not offer parallel execution but neither did the original zip implementation.

And as F. Böller has pointed out it doesn’t work if bs is infinite and as is not. For a solution which works for all possible combinations of infinite and finite streams, an intermediate Iterator which checks both sources within the hasNext method seems unavoidable¹:

static <A, B> Stream<Pair<A,B>> zip(Stream<A> as, Stream<B> bs) {
    Iterator<A> i1 = as.iterator();
    Iterator<B> i2 = bs.iterator();
    Iterable<Pair<A,B>> i=()->new Iterator<Pair<A,B>>() {
        public boolean hasNext() {
            return i1.hasNext() && i2.hasNext();
        }
        public Pair<A,B> next() {
            return new Pair<A,B>(i1.next(), i2.next());
        }
    };
    return StreamSupport.stream(i.spliterator(), false);
}

If you want parallel capable zipping you should consider the source of the Stream. E.g. you can zip two ArrayLists (or any RandomAccessList) like

ArrayList<Foo> l1=new ArrayList<>();
ArrayList<Bar> l2=new ArrayList<>();
IntStream.range(0, Math.min(l1.size(), l2.size()))
         .mapToObj(i->new Pair(l1.get(i), l2.get(i)))
         . …

¹(unless you implement a Spliterator directly)