首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Iterator诉for

Iterator诉for
EN

Stack Overflow用户
提问于 2014-03-08 10:09:55
回答 6查看 84.6K关注 0票数 100

我在一次采访中被问到,在for循环上使用迭代器有什么好处,或者使用for循环优于迭代器有什么好处?

有人能回答这个问题吗?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2014-03-08 10:47:07

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

代码语言:javascript
复制
for (int i = 0; i < list.size(); i++) {
    Thing t = list.get(i);
    ...
}

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

另一个,foreach循环在幕后使用一个Iterator:

代码语言:javascript
复制
for (Thing thing : list) {
    ...
}

这适用于所有类型的Iterable集合(或数组)。

最后,您可以使用Iterator,它也适用于任何Iterable:

代码语言:javascript
复制
for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
    Thing t = it.next();
    ...
} 

所以你实际上有三个循环来比较。

你可以用不同的术语来比较它们:性能,可读性,错误倾向性,能力.

Iterator可以执行foreach循环无法完成的任务。例如,如果迭代器支持元素,则可以在迭代过程中删除元素:

代码语言:javascript
复制
for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
    Thing t = it.next();
    if (shouldBeDeleted(thing) {
        it.remove();
    }
} 

列表还提供了可以双向迭代的迭代器。foreach循环只从开始循环到结束循环。

但是Iterator更危险,更不容易读懂。当您需要一个foreach循环时,它是最易读的解决方案。使用迭代器,您可以执行以下操作,这将是一个bug:

代码语言:javascript
复制
for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
    System.out.println(it.next().getFoo());
    System.out.println(it.next().getBar());
} 

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

在数组支持的集合中,使用索引访问元素的效率略高一些。但是,如果您改变主意,使用LinkedList而不是ArrayList,那么性能就会突然变得糟糕,因为每次访问list.get(i)时,链接的列表都必须循环遍历其所有元素,直到第一个元素。Iterator (因此是foreach循环)没有这个问题。它总是使用最好的方法来迭代给定集合的元素,因为集合本身有自己的Iterator实现。

我的一般经验法则是:使用foreach循环,除非您确实需要Iterator的功能。当我需要访问循环中的索引时,我只会使用带有数组的索引的for循环。

票数 163
EN

Stack Overflow用户

发布于 2014-03-08 10:15:25

Iterator优势:

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

循环被设计为只在Collection上迭代,所以如果您只想在Collection上迭代,最好使用循环(如for-Each ),但是如果您想要更多的循环,则可以使用Iterator。

票数 26
EN

Stack Overflow用户

发布于 2014-03-08 12:28:31

Iterator与经典的for循环之间的主要区别是,除了有或没有访问您正在迭代的项的索引这一显而易见的区别之外,使用Iterator从底层集合实现中抽象出客户端代码,请允许我详细说明。

当您的代码使用迭代器时,请使用以下两种形式

代码语言:javascript
复制
for(Item element : myCollection) { ... }

此表单

代码语言:javascript
复制
Iterator<Item> iterator = myCollection.iterator();
while(iterator.hasNext()) {    
    Item element = iterator.next();    
    ... 
}

或者这份表格

代码语言:javascript
复制
for(Iterator iterator = myCollection.iterator(); iterator.hasNext(); ) {
   Item element = iterator.next();
   ...
}

您的代码说的是“我不关心集合的类型及其实现,我只关心我可以迭代它的元素”。这通常是更好的方法,因为它使您的代码更加解耦。

另一方面,如果您使用的是经典的for循环,如

代码语言:javascript
复制
for(int i = 0; i < myCollection.size(); i++) {
   Item element = myCollection.get(i);
   ...
}

您的代码说,我需要知道集合的类型,因为我需要以一种特定的方式遍历它的元素,我也可能会根据迭代的顺序检查空值或计算某些结果。这使得您的代码更加脆弱,因为如果在任何时候您接收到的集合类型发生了更改,它将影响您的代码的工作方式。

总之,区别不在于速度或内存的使用,而在于代码的解耦,以便更灵活地应对变化。

票数 15
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22267919

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档