我们还需要迭代器设计模式吗?

发布于 2024-10-19 16:16:56 字数 72 浏览 1 评论 0 原文

我正在学习设计模式,我发现了迭代器。我们还需要使用它吗?

既然我们有集合,我很困惑为什么我们仍然需要迭代器设计模式。

I am learning the design patterns, and I found Iterator. Do we still need to use it?

Since we have collection, I am confused why we still need the Iterator Design Pattern.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

孤独患者 2024-10-26 16:16:56

IEnumerator 是一个迭代器,IEnumerable 创建它们。几乎所有集合都实现 IEnumerable

它是 Linq-To-Objects 的核心,而 Linq-To-Objects 是 C# 3 的核心功能之一。因此迭代器在现代 C# 中非常重要。

C# 3 还引入了一种特殊的语言功能,允许您使用 yield return 语法轻松实现迭代器。

foreach 也是基于迭代器的。

IEnumerator<T> is an iterator and IEnumerable<T> creates them. Almost all collections implement IEnumerable<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.

生来就爱笑 2024-10-26 16:16:56

事实上,在这两种语言中,集合都积极使用迭代器。每当您遍历集合的元素时,都会涉及某种迭代器,即使您没有在代码中明确看到它。我用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窗帘。

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:

for (Iterator i = c.iterator(); i.hasNext(); ) {
  doSomething((Element) i.next()); // (No generics before 1.5)
}

And since Java 5:

for (Element e : elements) {
  doSomething(e);
}

The latter results in practically identical bytecode though, using an Iterator behind the curtain.

梦幻的味道 2024-10-26 16:16:56

IEnumerable 接口正是迭代器模式:)

The IEnumerable interface is exactly the iterator pattern :)

飘落散花 2024-10-26 16:16:56

在 Java 中,迭代器还有其他用途,特别是 Iterator.remove() 仍然有用。

In Java, an Iterator has other uses, in particular the Iterator.remove() can still be useful.

世界如花海般美丽 2024-10-26 16:16:56

是的,我们仍然需要迭代器!

1) 在没有迭代器的情况下,循环链表的时间复杂度为O(n^2)

for (int i = 0; i < list.size(); i++)
  list.get(i).foo();

要到达元素 #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.

for (int i = 0; i < list.size(); i++)
  list.get(i).foo();

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.

遥远的绿洲 2024-10-26 16:16:56

迭代器和集合的不同之处在于,集合本质上是保存项,而迭代器只是一项一项地检索项,而不是包含在其中。

例如,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.

ゝ杯具 2024-10-26 16:16:56

在许多情况下,迭代未知数量的项目比将所有项目收集到集合中更有效。这里有几个例子说明了为什么迭代效率更高。在某些情况下甚至不可能使用集合。

  • 该列表基于缓慢的资源,无法一次提供所有项目。 (数据库读取器、文件、一些网络内容、计算)
  • 源仅允许前向游标(如磁带、数据库游标、服务器客户端流内容)
  • 正在生成列表 列表
  • 非常长,无法立即保存在内存中
  • 您是使用链表,获取下一个元素比获取索引 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.

  • The list is based on a slow resource, which cannot provide all items at once. (DB reader, file, some network stuff, calculation)
  • The source only allows forward cursors (like tapes, DB cursor, server client stream stuff)
  • The list is being generated
  • The list is extreme long and cannot be held in memory at once
  • You are using a linked list, where getting the next element is more efficient, than getting an element at index i.
  • After getting a source list, a new result should be created, based on that list. For example a source list should be filtered and converted. It wouldn't be efficient to save the result in a new list, when only some of the values would be reused.

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 using foreach.

熊抱啵儿 2024-10-26 16:16:56

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.

呆头 2024-10-26 16:16:56

集合封装了一组值的不同类型的组织——如集合、列表数组等。

迭代器封装/代表的是这些 -

  1. 以类型安全的方式对集合中任何一个存储项的引用。

即使我有一个字符串列表,我的内部列表
实现将使用包含字符串值的对象
以及下一个+上一个项目。迭代器隐藏了这些内部
否则可能会暴露的物体。

  1. 迭代它们的方法 -

取决于代表的实际对象的类型
迭代器迭代它们可能会有很大不同。例如在
数组,您将转到下一个索引。但你需要一份清单
访问下一个或上一个项目参考。

  1. 常见操作,如第一个、最后一个和下一个项目。

  2. 其他信息,例如迭代器特征,可让您了解使用迭代器支持的移动类型

因此,不要使用一个自定义的 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 -

  1. A reference to any one of the stored items in the collection in a type safe way.

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.

  1. A way to iterate through them -

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.

  1. Common operations like first last and next items.

  2. 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文