El siguiente código está usando el bucle for indexado:
List<A> a = ..; List<B> b = ..; List<C> c = ..; // a.size() == b.size() == c.size() - fundamental business logic assumption int size = a.size(); for (int i = 0; i < size; i++) { doSthWith(a.get(i)); doSthWith(b.get(i)); doSthWith(c.get(i)); }¿Es posible simplificar aún más el código y no usar el índice para iterar sobre tres listas simultáneamente?
Si las tres listas se iteran juntas como espera, eso significa que están estrechamente relacionadas y califican para ser un objeto de algún tipo. Implica una simplificación del diseño de antemano.
Class MyClass { A a; B b; C c; } Entonces tendré una List<MyClass> en lugar de tres listas con datos relacionados. Esto también simplificará su código a largo plazo.
Y, para responder a su pregunta, lo que sea que esté usando actualmente parece muy ingenuo, pero es la forma más legible de hacerlo si no se está tomando la molestia de hacer una clase.
Dado que se refiere a la lista por su interfaz, siempre debe preferir usar un Iterator en lugar de get() , porque no sabe si este último será igualmente eficiente.
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(); Puede crear su propio Iterator que encapsule la lógica anterior:
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; } }Puedes usar la función forEach :
a.forEach(o -> doSthWith(o));También puede usar la función para manejar cada lista:
Interfaz funcional:
@FunctionalInterface public interface ListConsumer<T extends Iterable> { void accept(T ... t); }Realización:
ListConsumer<List> function = (list) -> { for (List l: list) { doSthWith(l); } };Utilizando:
List a = new ArrayList(); List b = new ArrayList(); function.accept(a, b);