java—同时迭代三个列表

kpbpu008  于 2021-07-03  发布在  Java
关注(0)|答案(3)|浏览(284)

这个问题在这里已经有答案了

使用java流将两个大小相同(类型不同)的列表合并到域对象列表中(2个答案)
上个月关门了。
以下代码正在使用索引for循环:

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));
}

这是否可以进一步简化代码,而不使用索引同时迭代三个列表?

fumotvh3

fumotvh31#

你可以用 forEach 功能:

a.forEach(o -> doSthWith(o));

您还可以使用函数来处理每个列表:
功能接口:

@FunctionalInterface
public interface ListConsumer<T extends Iterable> {
    void accept(T ... t);
}

实现:

ListConsumer<List> function = (list) -> {
        for (List l:
             list) {
            doSthWith(l);
        }
    };

使用:

List a = new ArrayList();
    List b = new ArrayList();
    function.accept(a, b);
pexxcrt2

pexxcrt22#

如果所有三个列表都要像您所期望的那样迭代在一起,那就意味着它们是紧密相关的,并且有资格成为某种类型的对象。它需要事先简化设计。

Class MyClass {
   A a;
   B b;
   C c;
}

那我就去喝一杯 List<MyClass> 而不是三个相关数据的列表。从长远来看,这将简化您的代码。
而且,为了回答您的问题,您目前使用的任何方法似乎都非常幼稚,但如果您不承担制作类的辛苦,那么这是最可读的方法。

r6vfmomb

r6vfmomb3#

因为您是通过列表的接口来引用列表的,所以您应该总是喜欢使用 Iterator 相对于 get() ,因为你不知道后者是否同样有效。

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();

你可以自己创造 Iterator 它封装了上述逻辑:

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;
    }
}

相关问题