我们还需要迭代器设计模式吗?
我正在学习设计模式,我发现了迭代器。我们还需要使用它吗?
既然我们有集合,我很困惑为什么我们仍然需要迭代器设计模式。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
我正在学习设计模式,我发现了迭代器。我们还需要使用它吗?
既然我们有集合,我很困惑为什么我们仍然需要迭代器设计模式。
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(9)
IEnumerator
是一个迭代器,IEnumerable
创建它们。几乎所有集合都实现IEnumerable
。它是 Linq-To-Objects 的核心,而 Linq-To-Objects 是 C# 3 的核心功能之一。因此迭代器在现代 C# 中非常重要。
C# 3 还引入了一种特殊的语言功能,允许您使用
yield return
语法轻松实现迭代器。foreach
也是基于迭代器的。IEnumerator<T>
is an iterator andIEnumerable<T>
creates them. Almost all collections implementIEnumerable<T>
.It's at the heart of Linq-To-Objects which is one of the core features of C# 3. So iterators are very important in modern C#.
C# 3 also introduced a special language feature allowing you to easily implement an iterator using the
yield return
syntax.foreach
is based on iterators too.事实上,在这两种语言中,集合都积极使用迭代器。每当您遍历集合的元素时,都会涉及某种迭代器,即使您没有在代码中明确看到它。我用Java来举例,因为我对它比较熟悉。
在 Java 5 之前迭代集合的首选习惯用法 - 显式使用
Iterator
:从 Java 5 开始:
后者会产生几乎相同的字节码,但在后面使用
Iterator
窗帘。Collections in fact actively use iterators, in both languages. Whenever you walk through the elements of a collection, there is some sort of iterator involved, even if you don't see it explicitly in the code. I give examples in Java, as I am more familiar with it.
The preferred idiom to iterate over a collection prior to Java 5 - using an
Iterator
explicitly:And since Java 5:
The latter results in practically identical bytecode though, using an
Iterator
behind the curtain.IEnumerable 接口正是迭代器模式:)
The IEnumerable interface is exactly the iterator pattern :)
在 Java 中,迭代器还有其他用途,特别是 Iterator.remove() 仍然有用。
In Java, an Iterator has other uses, in particular the Iterator.remove() can still be useful.
是的,我们仍然需要迭代器!
1) 在没有迭代器的情况下,循环链表的时间复杂度为
O(n^2)
。要到达元素 #5,列表从头元素开始并遵循 4 个链接。为了在下一个循环中到达元素#6,它再次从头部开始,遵循所有相同的链接(加一个)。迭代器足够聪明,可以记住最后的位置,从而给出
O(n)
。快多了!2)
size()
有问题。有时您还不知道尺寸。某些生产者线程可能正在添加元素,而另一个线程想要开始读取。如果它首先需要大小,(for(i=0;i),它无法在生产者线程完成之前启动。
集合可能太大,以至于内存中无法容纳所有元素。迭代器一次仅提供对一个元素的访问,因此它只需要适合一个元素。
3)如何循环遍历一棵树的所有元素?编写没有错误的代码并不是那么简单。幸运的是,您可以获得树中所有元素的迭代器,并愉快地迭代它们,而不必担心顺序或其他任何事情。
迭代器隐藏了元素的存储方式,仅提供访问,这是一个很好的抽象。
Yes, we still need iterators!
1) Looping through linked lists is
O(n^2)
in time without iterators.To get to element #5, the list starts at the head element and follows 4 links. To get to element #6 on the next loop, it starts at the head again, following all the same links (plus one). An iterator would be clever enough to remember the last position, giving
O(n)
. A lot faster!2) There is a problem with
size()
. Sometimes you don't know the size yet. Some producer thread could be adding elements, while another thread wants to start reading. If it needs the size first, (for(i=0;i<size;i++)
) it can not start before the producer thread has finished.A collection might be so big, that the elements don't fit in memory all together. An iterator only provides access to one element at a time, so it needs to fit in only one element.
3) How to loop through all the elements of a tree? To write that code bug free isn't that simple. Luckily, you can get an iterator to all the elements in the tree and happily iterate through them, not having to worry about order or anything.
The iterator hides how the elements are stored and only provides access, a nice abstraction.
迭代器和集合的不同之处在于,集合本质上是保存项,而迭代器只是一项一项地检索项,而不是包含在其中。
例如,IDataReader 是数据库项的迭代器,您可以有一个用于文件系统中目录项的 IEnumerable 迭代器,以及一个集合的迭代器。
Iterator and collection are different in that a collection essentially is holding items, and an iterator just retrieves items one by one, not contained within it.
For example, an IDataReader is an iterator to database items, and you could have an IEnumerable iterator to directory entries in a file system, as well as an iterator to a collection.
在许多情况下,迭代未知数量的项目比将所有项目收集到集合中更有效。这里有几个例子说明了为什么迭代效率更高。在某些情况下甚至不可能使用集合。
i
处的元素更有效。最后一个例子涉及 linq 或类似的方法,可以有效地转换复杂的对象结构。
此外,使用
for
循环来处理所有项目比使用foreach
更复杂。In many cases it is more efficient to iterate over an unknown number of items instead of collecting all of them in a collection. Here are several examples which show, why iterating is more efficient. In some cases it even isn't possible to use collections.
i
.The last example refersd to linq or similiar approaches, where complex object structures can be transformed efficiently.
Additionally it is mostly more complicated to use a
for
loop to handle all items instead of usingforeach
.Java 和 C# 集合在底层使用迭代器模式。这几乎是可变集合的必需品。
如果您选择使用持久集合(例如,Functional Java 库中提供的集合),则将不再需要迭代器模式。
The Java and C# collections use the iterator pattern under the hood. It is almost a necessity for mutable collections.
If you instead choose to use the persistent collections (for example, those provided in the Functional Java library), you would no longer need the iterator pattern.
集合封装了一组值的不同类型的组织——如集合、列表数组等。
迭代器封装/代表的是这些 -
即使我有一个字符串列表,我的内部列表
实现将使用包含字符串值的对象
以及下一个+上一个项目。迭代器隐藏了这些内部
否则可能会暴露的物体。
取决于代表的实际对象的类型
迭代器迭代它们可能会有很大不同。例如在
数组,您将转到下一个索引。但你需要一份清单
访问下一个或上一个项目参考。
常见操作,如第一个、最后一个和下一个项目。
其他信息,例如迭代器特征,可让您了解使用迭代器支持的移动类型
因此,不要使用一个自定义的 for 循环向量和另一个用于访问映射元素的自定义循环以及另一个用于访问列表集合的自定义循环,我们现在可以拥有一个可应用于任何这些类型的访问循环。
事实上,这使得基于模板的算法成为可能,因为它们现在只需要专注于对内容或集合所做的操作,而忽略传递给它们的集合的类型。
我什至可以说迭代器模式是最简单和基本的项目,STL 等模板集合的整个概念都是从它开始的。
Collections encapsulate different types of organizations for a group of values - as in a set, list arrays and such.
What Iterators encapsulate / represent are these -
Even though i have a list of strings, my internal list
implementation would be using an object containing the String value
along with next + previous items. Iterator hides these internal
objects which might have been exposed otherwise.
Depending on the type of the actual object that represents the
iterator iterating through them might be vastly different. eg on an
array you would go to the next index. But ona list you would need
to access the next or previous item references.
Common operations like first last and next items.
Additional information like iterator traits that let you know the type of movements supported using the iterator
So instead of having one custom for loop for vector and another custom loop for acessing the element of maps and another custom loop for accessing the collection of a list, we can now have a single access loop that can be applied to any of these types.
In fact this is what makes template based algorithms possible as they now need to only concentrate on what they do with the contents or collections and ignore the type of collections passed to them.
I would go so far as to say that the iterator pattern is the simplest and basic item from which the entire concept of template collections like STL starts.