我们还需要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封装/表示的是这些 –
- 以类型安全的方式引用集合中任何一个存储的项目。
即使我有一个字符串列表,我的内部列表实现将使用包含String值的对象以及next + previous项。 迭代器隐藏了这些可能已经暴露的内部对象。
- 迭代它们的方法 –
根据表示迭代器的实际对象的类型,迭代它们可能会有很大的不同。 例如,在数组上,您将转到下一个索引。 但是在列表中,您需要访问下一个或上一个项目引用。
-
常见操作,如前一个和下一个项目。
-
其他信息,如迭代器特性,可以让您知道使用迭代器支持的移动类型
因此,我们现在可以拥有一个可以应用于任何这些类型的访问循环,而不是为vector提供一个自定义for循环,而另一个用于访问map元素的自定义循环和另一个用于访问列表集合的自定义循环。
实际上,这使得基于模板的算法成为可能,因为他们现在只需要专注于他们对内容或集合的处理,并忽略传递给它们的集合类型。
我甚至会说迭代器模式是最简单和最基本的项目,像STL这样的模板集合的整个概念从这个项目开始。