Provide an iterator over the contents of two lists simultaneously?

This is copied+edited from Stephen C's answer. Feel free to use:

public class Pair<T1, T2> {
    private final T1 v1;
    private final T2 v2;
    Pair(T1 v1, T2 v2) {
        this.v1 = v1;
        this.v2 = v2;
    }
    public T1 first(){
        return v1;
    }
    public T2 second(){
        return v2;
    }
}

public class ParallelIterator <T1, T2> implements Iterator<Pair<T1, T2>> {

    private final Iterator<T1> it1;
    private final Iterator<T2> it2;

    public ParallelIterator(Iterator<T1> it1, Iterator<T2> it2) { 
        this.it1 = it1; this.it2 = it2;
    }

    @Override
    public boolean hasNext() { return it1.hasNext() && it2.hasNext(); }

    @Override
    public Pair<T1, T2> next() {
        return new Pair<T1, T2>(it1.next(), it2.next());
    }

    @Override
    public void remove(){
        it1.remove();
        it2.remove();
    }
}

public class IterablePair <T1, T2> implements Iterable<Pair<T1,T2>> {
    private final List<T1> first;
    private final List<T2> second;

    public IterablePair(List<T1> first, List<T2> second) { 
        this.first = first;
        this.second = second;
    }

    @Override
    public Iterator<Pair<T1, T2>> iterator(){
        return new ParallelIterator<T1,T2>( first.iterator(), second.iterator() );
    }
}

void someFunction(){
    IterablePair<X,Y> listPair = new IterablePair<X,Y>( x, y );
    for( Pair<X,Y> pair : listPair ){
        X x = pair.first();
        ...
    }
}

This stops as soon as either list is out of elements, so you might want to check lists have equal size before creating an IterablePair.


Anyway, the problem is that I can't really return just a single object from next(), and I also can't have a Iterator take more than one type. So, any thoughts?

Obviously you are going to need a light-weight "pair" class. This is roughly analogous to the Map.Entry inner class.

Here's a rough cut at a generic solution:

public class ParallelIterator <T1, T2> implements Iterator<Pair<T1, T2>> {

    public class Pair<TT1, TT2> {
        private final TT1 v1;
        private final TT2 v2;
        private Pair(TT1 v1, TT2 v2) { this.v1 = v1; this.v2 = v2; }
        ...
    }

    private final Iterator<T1> it1;
    private final Iterator<T2> it2;

    public ParallelIterator(Iterator<T1> it1, Iterator<T2> it2) { 
        this.it1 = it1; this.it2 = it2;
    }

    public boolean hasNext() { return it1.hasNext() && it2.hasNext(); }

    public Pair<T1, T2> next() {
        return new Pair<T1, T2>(it1.next(), it2.next());
    }

    ...

}

Note: this doesn't explicitly deal with cases where the lists have different lengths. What will happen is that extra elements at the end of the longer list will be silently ignored.