我在一次采访中被问到,在for循环上使用迭代器有什么好处,或者使用for循环优于迭代器有什么好处?
有人能回答这个问题吗?
发布于 2014-03-08 10:47:07
首先,有两种for循环,它们的行为非常不同。一种是使用指数:
for (int i = 0; i < list.size(); i++) {
Thing t = list.get(i);
...
}这种循环并不总是可能的。例如,列表有索引,但集合没有索引,因为它们是无序集合。
另一个,foreach循环在幕后使用一个Iterator:
for (Thing thing : list) {
...
}这适用于所有类型的Iterable集合(或数组)。
最后,您可以使用Iterator,它也适用于任何Iterable:
for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
Thing t = it.next();
...
} 所以你实际上有三个循环来比较。
你可以用不同的术语来比较它们:性能,可读性,错误倾向性,能力.
Iterator可以执行foreach循环无法完成的任务。例如,如果迭代器支持元素,则可以在迭代过程中删除元素:
for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
Thing t = it.next();
if (shouldBeDeleted(thing) {
it.remove();
}
} 列表还提供了可以双向迭代的迭代器。foreach循环只从开始循环到结束循环。
但是Iterator更危险,更不容易读懂。当您需要一个foreach循环时,它是最易读的解决方案。使用迭代器,您可以执行以下操作,这将是一个bug:
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循环。
发布于 2014-03-08 10:15:25
Iterator优势:
next()和previous()向前和向后移动。hasNext()检查是否有更多的元素。循环被设计为只在Collection上迭代,所以如果您只想在Collection上迭代,最好使用循环(如for-Each ),但是如果您想要更多的循环,则可以使用Iterator。
发布于 2014-03-08 12:28:31
Iterator与经典的for循环之间的主要区别是,除了有或没有访问您正在迭代的项的索引这一显而易见的区别之外,使用Iterator从底层集合实现中抽象出客户端代码,请允许我详细说明。
当您的代码使用迭代器时,请使用以下两种形式
for(Item element : myCollection) { ... }此表单
Iterator<Item> iterator = myCollection.iterator();
while(iterator.hasNext()) {
Item element = iterator.next();
...
}或者这份表格
for(Iterator iterator = myCollection.iterator(); iterator.hasNext(); ) {
Item element = iterator.next();
...
}您的代码说的是“我不关心集合的类型及其实现,我只关心我可以迭代它的元素”。这通常是更好的方法,因为它使您的代码更加解耦。
另一方面,如果您使用的是经典的for循环,如
for(int i = 0; i < myCollection.size(); i++) {
Item element = myCollection.get(i);
...
}您的代码说,我需要知道集合的类型,因为我需要以一种特定的方式遍历它的元素,我也可能会根据迭代的顺序检查空值或计算某些结果。这使得您的代码更加脆弱,因为如果在任何时候您接收到的集合类型发生了更改,它将影响您的代码的工作方式。
总之,区别不在于速度或内存的使用,而在于代码的解耦,以便更灵活地应对变化。
https://stackoverflow.com/questions/22267919
复制相似问题