为啥java Iterator接口应该实现为内部类?

Posted

技术标签:

【中文标题】为啥java Iterator接口应该实现为内部类?【英文标题】:Why java Iterator interface should be implemented as inner class?为什么java Iterator接口应该实现为内部类? 【发布时间】:2013-04-18 16:52:02 【问题描述】:

我最近读了一本书“Java 教程”第 3 版。 如图所示,讲的是内部类的实现。

在第 3 段中,它说“Stack 类本身不应该实现 Iterator 接口,因为...”。

我找不到任何 Stack 类不应该实现 Iterator 的原因。给出的理由并不普遍。

你能解释一下吗?

【问题讨论】:

【参考方案1】:

从根本上说,迭代器是有状态的——它需要知道它在集合中指向的位置。这不属于集合本身的一部分——给出的解释是正确的……完全有可能有两个独立的迭代器对象,迭代同一个集合对象。如果集合本身实现了 Iterator 接口,您将如何建模?这是可能(例如,创建一个集合的新实例,该实例又包含对原始集合的引用),但它真的很难看。

这里有不同的问题:

数据的收集 位于集合中的光标

单独的关注点 => 单独的类。

说服自己这一点的最简单方法可能是尝试实现自己的集合 - 然后拥有多个迭代器。例如,您可能想尝试:

List<String> foo = new MyListImplementation<String>();
foo.add("a");
foo.add("b");

// The enhanced for loop uses Iterable/Iterator for non-arrays
for (String x : foo) 
    for (String y : foo) 
        System.out.println(x + " " + y);
    

应该打印出来:

a a
a b
b a
b b

尝试在没有两个类的情况下实现它,看看你是怎么做的,牢记关注点分离。

【讨论】:

【参考方案2】:

堆栈不应该实现迭代器本身,因为那样你一次只能有一个迭代器,并且迭代堆栈会改变堆栈。

对于后一个问题,请注意嵌套类有一个“currentItem”字段。该字段需要在“堆栈”中,并且在调用 next() 时会更改。迭代集合不应更改集合。

第一个问题更严重:假设两个人在堆栈上进行迭代(或者一个方法希望在堆栈上创建两个迭代器)。那么如果iterator() 返回this,那么这两个迭代器就是同一个东西。在其中一个上调用next() 会移动另一个。混乱。

【讨论】:

【参考方案3】:

Stack 不能是它自己的Iterator,因为堆栈支持多个迭代器。

您可能希望多次迭代堆栈。这些迭代可能发生在不同的时间,甚至是同一时间。同时多次迭代显然需要多个对象。不同时间的多次迭代需要多个对象,因为Iterator接口不支持返回起点。

【讨论】:

“两个对象无法同时枚举 Stack 中的项目”。这两个对象是什么?它们是 Stack 的实例吗? 措辞不好。它指的是两个不同的实体,它们都想在同一个堆栈上进行迭代。这些实体可能是引用同一个堆栈的两个不同对象,也可能是不同的方法或不同的线程。 谢谢,KEY 是几个“实体”,它们持有对堆栈或堆栈迭代器的相同引用。【参考方案4】:

我能想到的原因有两个。

多种类型的迭代器

您可能需要以不同方式迭代的多种类型的迭代器。例如,前向迭代器和后向迭代器(从容器末尾迭代到开头)。

多个实例的迭代器

如果您有多次传递算法和/或嵌套循环,则每个循环可能都需要自己的迭代器,以便独立于其他迭代器跟踪它在容器中的位置。


使用在Stack 类中实现的Iterator 接口支持这些功能即使不是不可能也很困难。

【讨论】:

大字体有什么特殊原因吗? 是的。这是合理的。但我仍然不知道教科书上给出的原因。 “两个对象无法同时枚举堆栈中的项目”。这两个对象是什么?它们是 Stack 的实例吗? @Zachery 我认为这本书在这方面具有误导性。我认为它的设想是如果你有一个堆栈s,然后你有两个对象foobar,每个对象都有一个指向s 的指针(也许s 被传递到了foobar 实例)。如果这些对象想要遍历s,除非它们有自己的私有迭代器,否则它们会互相妨碍。更一般地说,您还可以有一个函数/方法,它需要两个迭代器来指向同一个 Stack 实例。您不需要“单独的对象”遇到麻烦。【参考方案5】:

只是为了补充讨论,内部类将有权访问 Stack 类的私有数据,因此通过这种方式,Stack 类将设法处理客户端程序员一个对象,或多个对象(迭代器(s ),并且这些对象仍然能够访问该类并提供对集合的单独迭代。

【讨论】:

以上是关于为啥java Iterator接口应该实现为内部类?的主要内容,如果未能解决你的问题,请参考以下文章

java 中 iterator 为啥翻译成迭代器呢

为啥Java禁止继承内部接口?

java Iterable接口为啥不能带泛型通配符?或者:为啥我不能重写 iterator() 方法为子类返回一个 Iterator?

Java源码分析:深入探讨Iterator模式

java iterator方法

JAVA设计模式之迭代器设计模式