Iterator vs for

roc*_*ing 65 java iterator for-loop

我在接受采访时被问到使用for循环使用迭代器的优点是什么?使用for循环迭代器的优点是什么?

任何人都可以回答这个问题,以便将来如果我面临类似的问题那么我可以回答这个问题

JB *_*zet 110

首先,有2种for循环,其行为有很大不同.一个使用指数:

for (int i = 0; i < list.size(); i++) {
    Thing t = list.get(i);
    ...
}
Run Code Online (Sandbox Code Playgroud)

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

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

for (Thing thing : list) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

这适用于各种Iterable集合(或数组)

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

for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
    Thing t = it.next();
    ...
} 
Run Code Online (Sandbox Code Playgroud)

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

您可以用不同的术语对它们进行比较:性能,可读性,错误倾向,功能.

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

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

列表还提供可以在两个方向上迭代的迭代器.foreach循环仅从开始到结束迭代.

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

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

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

使用索引访问元素对于由数组支持的集合稍微更有效.但是如果你改变主意并使用LinkedList而不是ArrayList,突然性能将会非常糟糕,因为每次访问时list.get(i),链表都必须遍历所有元素,直到第i个元素为止.迭代器(以及foreach循环)没有这个问题.它始终使用最佳方式迭代给定集合的元素,因为集合本身具有自己的Iterator实现.

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

  • 你说的那个“ith”是英语的挑战。 (2认同)

Sal*_*lah 17

迭代器优势:

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

Loop的设计只是为了迭代a Collection,所以如果你只想迭代a Collection,最好使用循环for-Each,但是如果你想要更多,你可以使用Iterator.

  • 并且使用`ListIterator` 你还可以`add` 并在任意点开始迭代。 (2认同)

use*_*677 11

如果按编号访问数据(例如"i"),则使用数组时速度很快.因为它直接进入元素

但是,其他数据结构(例如树,列表),它需要更多时间,因为它从第一个元素开始到目标元素.当你使用列表.它需要时间O(n).所以,它会很慢.

如果你使用迭代器,编译器知道你在哪里.所以它需要O(1)(因为它从当前位置开始)

最后,如果您只使用支持直接访问的数组或数据结构(例如java中的arraylist)."a [i]"很好.但是,当您使用其他数据结构时,迭代器更有效


xbu*_*gos 10

Iterator和经典for循环之间的主要区别,除了显而易见的是有或无法访问您正在迭代的项的索引之外,是使用Iterator从底层集合实现中抽象出客户端代码,允许我阐述.

当您的代码使用迭代器时,请使用此窗体

for(Item element : myCollection) { ... }
Run Code Online (Sandbox Code Playgroud)

这个表格

Iterator<Item> iterator = myCollection.iterator();
while(iterator.hasNext()) {    
    Item element = iterator.next();    
    ... 
}
Run Code Online (Sandbox Code Playgroud)

或这个表格

for(Iterator iterator = myCollection.iterator(); iterator.hasNext(); ) {
   Item element = iterator.next();
   ...
}
Run Code Online (Sandbox Code Playgroud)

你的代码所说的是"我不关心集合的类型及其实现,我只关心我可以迭代它的元素".这通常是更好的方法,因为它使您的代码更加分离.

另一方面,如果你使用经典的for循环,就像在

for(int i = 0; i < myCollection.size(); i++) {
   Item element = myCollection.get(i);
   ...
}
Run Code Online (Sandbox Code Playgroud)

你的代码说,我需要知道集合的类型,因为我需要以特定的方式迭代它的元素,我也可能会检查空值或根据迭代的顺序计算一些结果.这会使您的代码更加脆弱,因为如果您收到的集合类型随时发生变化,则会影响代码的工作方式.

总结一下,差异不在于速度或内存使用,更多的是解耦代码,以便更灵活地应对变化.


fgu*_*gul 5

与其他答案不同,我想指出另一件事;

\n\n

如果您需要在代码中的多个位置执行迭代,您可能最终会重复逻辑。这显然不是一个非常可扩展的方法。相反,\xe2\x80\x99s 需要的是一种将选择数据的逻辑与实际处理数据的代码分开的方法。

\n\n

迭代通过提供用于循环一组数据的通用接口来解决这些问题,从而隐藏底层数据结构或存储机制 \xe2\x80\x94(例如数组)。

\n\n
    \n
  • 迭代器是一个概念而不是实现。
  • \n
  • 迭代器提供了许多用于遍历和访问数据的操作。
  • \n
  • 迭代器可以包装任何数据结构,例如数组。
  • \n
  • 使用迭代器的更有趣和有用的优点之一是能够包装或装饰另一个迭代器以过滤返回值
  • \n
  • 迭代器可能是线程安全的,而单独的 for 循环则不能,因为它直接访问元素。唯一流行的线程安全迭代器是CopyOnWriteArrayList但它众所周知并且经常使用,因此值得一提。
  • \n
\n\n

这是来自这本书,它是https://www.amazon.com/Beginning-Algorithms-Simon-Harris/dp/0764596748

\n