迭代器 vs for

2022-08-31 10:36:46

在一次采访中,有人问我使用迭代器对循环的优势是什么,或者使用循环器对迭代器的优势是什么?forfor

任何人都可以回答这个问题吗?


答案 1

首先,有 2 种 for 循环,它们的行为非常不同。一个使用指数:

for (int i = 0; i < list.size(); i++) {
    Thing t = list.get(i);
    ...
}

这种循环并不总是可能的。例如,列表有索引,但集合没有,因为它们是无序集合。

另一个,foreach 循环在幕后使用迭代器:

for (Thing thing : list) {
    ...
}

这适用于每种可迭代集合(或数组)

最后,您可以使用迭代器,它也可以与任何可迭代对象一起使用:

for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
    Thing t = it.next();
    ...
} 

所以你实际上有3个循环可以比较。

您可以从不同的术语中比较它们:性能,可读性,易出错性,功能。

迭代器可以执行 foreach 循环无法执行的操作。例如,您可以在迭代时删除元素(如果迭代器支持):

for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
    Thing t = it.next();
    if (shouldBeDeleted(thing) {
        it.remove();
    }
} 

列表还提供了可以在两个方向上迭代的迭代器。foreach 循环仅从头到尾迭代。

但是迭代器更危险,可读性更差。当您只需要一个 foreach 循环时,它就是最具可读性的解决方案。使用迭代器,您可以执行以下操作,这将是一个错误:

for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
    System.out.println(it.next().getFoo());
    System.out.println(it.next().getBar());
} 

foreach 循环不允许发生这样的 bug。

使用索引访问元素对于由数组支持的集合的效率略高。但是,如果您改变主意并使用LinkedList而不是ArrayList,那么突然间性能将变得糟糕,因为每次您访问时,链表将不得不循环遍历其所有元素,直到第i个元素。迭代器(以及 foreach 循环)没有这个问题。它始终使用最佳方式来循环访问给定集合的元素,因为集合本身具有自己的迭代器实现。list.get(i)

我的一般经验法则是:使用 foreach 循环,除非你真的需要迭代器的功能。我只使用带有数组的索引的for循环,当我需要访问循环内的索引时。


答案 2

迭代器优势:

  • 能够从集合中删除元素。
  • 能够使用 和 向前和向后移动。next()previous()
  • 能够使用 检查是否有更多元素。hasNext()

Loop 被设计为只迭代 a ,所以如果你只想迭代 一个 ,最好使用 循环,如 ,但是如果你想要更多,你可以使用 Iterator。CollectionCollectionfor-Each