我们还需要Iterator设计模式吗?

嗨伙计们,我正在学习设计模式,我找到了Iterator。 我们还需要使用它吗? 由于我们有collections,我很困惑为什么我们仍然需要Iterator设计模式。

谢谢

事实上,集合在两种语言中都主动使用迭代器。 每当你遍历集合的元素时,都会涉及某种迭代器,即使你没有在代码中明确地看到它。 我用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产生几乎相同的字节码。

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

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

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

foreach也基于迭代器。

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

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

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

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 )它在生产者线程完成之前无法启动。

一个集合可能太大了,元素不能完全适合内存。 迭代器一次只提供对一个元素的访问,因此它只需要适合一个元素。

3)如何遍历树的所有元素? 要编写代码bug免费并不是那么简单。 幸运的是,你可以获得树中所有元素的迭代器,并愉快地遍历它们,而不必担心订单或任何事情。

迭代器隐藏了元素的存储方式,只提供了访问,这是一个很好的抽象。

迭代器和集合的不同之处在于集合本质上是持有项目,而迭代器只是逐个检索项目,而不包含在其中。

例如,IDataReader是数据库项的迭代器,您可以拥有文件系统中目录条目的IEnumerable迭代器,以及集合的迭代器。

在许多情况下,迭代未知数量的项目而不是在集合中收集所有项目更有效。 以下是几个示例,说明为什么迭代更有效。 在某些情况下,甚至无法使用集合。

  • 该列表基于缓慢的资源,不能一次提供所有项目。 (数据库阅读器,文件,一些网络资料,计算)
  • 源只允许前向游标(如磁带,数据库游标,服务器客户端流的东西)
  • 该列表正在生成中
  • 该列表非常长,不能立即保存在内存中
  • 您正在使用链接列表,其中获取下一个元素比在索引i处获取元素更有效。
  • 获取源列表后,应根据该列表创建新结果。 例如,应该过滤和转换源列表。 将结果保存在新列表中时,将只重用某些值时效率不高。

最后一个示例涉及linq或类似的方法,其中可以有效地转换复杂的对象结构。 另外,使用for循环处理所有项而不是使用foreach更加复杂。

Java和C#集合使用引擎盖下的迭代器模式。 它几乎是可变集合的必需品。

如果您选择使用持久性集合(例如,Functional Java库中提供的那些集合),则不再需要迭代器模式。

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

Iterators封装/表示的是这些 –

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

即使我有一个字符串列表,我的内部列表实现将使用包含String值的对象以及next + previous项。 迭代器隐藏了这些可能已经暴露的内部对象。

  1. 迭代它们的方法 –

根据表示迭代器的实际对象的类型,迭代它们可能会有很大的不同。 例如,在数组上,您将转到下一个索引。 但是在列表中,您需要访问下一个或上一个项目引用。

  1. 常见操作,如前一个和下一个项目。

  2. 其他信息,如迭代器特性,可以让您知道使用迭代器支持的移动类型

因此,我们现在可以拥有一个可以应用于任何这些类型的访问循环,而不是为vector提供一个自定义for循环,而另一个用于访问map元素的自定义循环和另一个用于访问列表集合的自定义循环。

实际上,这使得基于模板的算法成为可能,因为他们现在只需要专注于他们对内容或集合的处理,并忽略传递给它们的集合类型。

我甚至会说迭代器模式是最简单和最基本的项目,像STL这样的模板集合的整个概念从这个项目开始。