Since you are referring to the list by its interface, you should always prefer using an Iterator as opposed to get(), because you do not know whether the latter will be equally efficient.
Iterator<A> aIterator = aList.iterator();
Iterator<B> bIterator = bList.iterator();
Iterator<C> cIterator = cList.iterator();
while (aIterator.hasNext()) {
assert bIterator.hasNext();
assert cIterator.hasNext();
A a = aIterator.next();
B b = bIterator.next();
C c = cIterator.next();
}
assert !bIterator.hasNext();
assert !cIterator.hasNext();
You could create your own Iterator which encapsulates the above logic:
for (Three<A, B, C> three : ThreeIterator.iterate(aList, bList, cList)) {
A a = three.getA();
B b = three.getB();
C c = three.getC();
}
public class ThreeIterator<A, B, C> implements Iterator<Three<A, B, C>> {
private final Iterator<A> aIterator;
private final Iterator<B> bIterator;
private final Iterator<C> cIterator;
public ThreeIterator(Collection<A> aCollection, Collection<B> bCollection, Collection<C> cCollection) {
aIterator = aCollection.iterator();
bIterator = bCollection.iterator();
cIterator = cCollection.iterator();
}
@Override
public boolean hasNext() {
boolean result = aIterator.hasNext();
if (result) {
assert bIterator.hasNext();
assert cIterator.hasNext();
} else {
assert !bIterator.hasNext();
assert !cIterator.hasNext();
}
return result;
}
@Override
public Three<A, B, C> next() {
return new Three<>(aIterator.next(), bIterator.next(), cIterator.next());
}
@Override
public void remove() {
aIterator.remove();
bIterator.remove();
cIterator.remove();
}
public static <A, B, C> Iterable<Three<A, B, C>> iterate(List<A> aList, List<B> bList, List<C> cList) {
return new Iterable<Three<A, B, C>>() {
@Override
public Iterator<Three<A, B, C>> iterator() {
return new ThreeIterator<>(aList, bList, cList);
}
@Override
public Spliterator<Three<A, B, C>> spliterator() {
int size = aList.size();
assert bList.size() == size;
assert cList.size() == size;
return Spliterators.spliterator(iterator(), size, 0);
}
};
}
}
public class Three<A, B, C> {
private final A a;
private final B b;
private final C c;
public Three(A a, B b, C c) {
this.a = a;
this.b = b;
this.c = c;
}
public A getA() {
return a;
}
public B getB() {
return b;
}
public C getC() {
return c;
}
}