由于
答案 0 :(得分:7)
事实上,集合在两种语言中都主动使用迭代器。每当你遍历集合的元素时,都会涉及某种迭代器,即使你没有在代码中明确地看到它。我用Java来举例,因为我对它更熟悉。
在Java 5之前迭代集合的首选习惯用法 - 明确使用Iterator
:
for (Iterator i = c.iterator(); i.hasNext(); ) {
doSomething((Element) i.next()); // (No generics before 1.5)
}
从Java 5开始:
for (Element e : elements) {
doSomething(e);
}
后者导致实际上相同的字节码,在幕后使用Iterator
。
答案 1 :(得分:7)
IEnumerator<T>
是一个迭代器,IEnumerable<T>
创建它们。几乎所有馆藏都实施IEnumerable<T>
。
它是Linq-To-Objects的核心,这是C#3的核心功能之一。因此迭代器在现代C#中非常重要。
C#3还引入了一种特殊的语言功能,允许您使用yield return
语法轻松实现迭代器。
foreach
也基于迭代器。
答案 2 :(得分:2)
IEnumerable 接口正是迭代器模式:)
答案 3 :(得分:2)
在Java中,Iterator有其他用途,特别是Iterator.remove()仍然有用。
答案 4 :(得分:2)
是的,我们仍然需要迭代器!
1)在没有迭代器的情况下,在链接列表中循环O(n^2)
。
for (int i = 0; i < list.size(); i++)
list.get(i).foo();
要进入元素#5,列表从head元素开始,后跟4个链接。要在下一个循环中到达元素#6,它会再次从头开始,跟随所有相同的链接(加一)。迭代器很聪明,可以记住最后一个位置,给出O(n)
。快得多!
2)size()
存在问题。有时候你还不知道它的大小。一些生产者线程可能正在添加元素,而另一个线程想要开始阅读。如果它首先需要大小,(for(i=0;i<size;i++)
)它在生成器线程完成之前无法启动。
一个集合可能太大了,元素不能完全适合内存。迭代器一次只提供对一个元素的访问,因此它只需要适合一个元素。
3)如何遍历树的所有元素?要编写代码bug免费并不那么简单。幸运的是,你可以获得树中所有元素的迭代器,并愉快地遍历它们,而不必担心订单或任何事情。
迭代器隐藏了元素的存储方式,只提供了访问,这是一个很好的抽象。
答案 5 :(得分:1)
迭代器和集合的不同之处在于集合本质上是持有项目,而迭代器只是逐个检索项目,而不包含在其中。
例如,IDataReader是数据库项的迭代器,您可以拥有一个IEnumerable迭代器来处理文件系统中的目录条目,以及一个集合的迭代器。
答案 6 :(得分:1)
在许多情况下,迭代未知数量的项目而不是在集合中收集所有项目更有效。以下是几个示例,说明为什么迭代更有效。在某些情况下甚至无法使用集合。
i
获取元素更有效。最后一个例子涉及linq或类似的方法,其中可以有效地转换复杂的对象结构。
此外,使用for
循环来处理所有项目而不是使用foreach
更加复杂。
答案 7 :(得分:0)
Java和C#集合使用底层的迭代器模式。它几乎是可变集合的必需品。
如果您选择使用持久性集合(例如,功能Java库中提供的那些集合),则不再需要迭代器模式。
答案 8 :(得分:0)
集合为一组值封装了不同类型的组织 - 如集合,列表数组等。
Iterators封装/表示的是这些 -
即使我有一个字符串列表,我的内部列表 实现将使用包含String值的对象 以及下一个+上一个项目。迭代器隐藏了这些内部 可能已经暴露的对象。
取决于代表的实际对象的类型 迭代它们的迭代器可能会有很大的不同。例如 数组你会去下一个索引。但是你需要的列表 访问下一个或上一个项目引用。
常见的操作,如前一个和下一个项目。
其他信息,如迭代器特性,让您知道使用迭代器支持的移动类型
因此,我们现在可以拥有一个可以应用于任何一个的单一访问循环,而不是为vector提供一个自定义for循环,而另一个自定义循环用于访问map元素和另一个用于访问列表集合的自定义循环。这些类型。
事实上,这使得基于模板的算法成为可能,因为他们现在只需要专注于对内容或集合的处理,并忽略传递给它们的集合类型。
我甚至会说迭代器模式是最简单和基本的项目,像STL这样的模板集合的整个概念从这个项目开始。