【问题标题】:what is the need to have listIterator() and iterator() in the list interface in Java?在 Java 的列表接口中需要 listIterator() 和 iterator() 吗?
【发布时间】:2013-11-16 22:05:48
【问题描述】:

List 接口有两个方法listIterator()iterator()。为什么这两个都需要。

来自docs:

Iterator<E> iterator()

Returns an iterator over the elements in this list in proper sequence.

ListIterator<E> listIterator()

Returns a list iterator over the elements in this list (in proper sequence).

    ListIterator<E> listIterator(int index)

    Returns a list iterator over the elements in this list (in proper sequence), starting at the 
specified position in the list. The specified index indicates the first element that would be 
returned by an initial call to next. An initial call to previous would return the element with the 
specified index minus one.

所以基本上,ListIterator() 有这个额外的方法来获取 previous and next 元素,而 Iterator() 只有 next 元素。难道这只是为了这个目的,还有一个ListIterator() interfacelistiterator() method in List inteface

【问题讨论】:

标签: java list iterator


【解决方案1】:

从 Java 5 开始,可以简单地使用更具体的返回类型(称为协变返回类型)覆盖方法。但是ListIterator 已在 Java 1.2 中引入。为避免对iterator() 的使用进行强制转换,必须有一种新方法。

不能从 Java 5 开始更改 API,因为这会破坏 List 的所有实现,这些实现不声明 iterator() 返回 ListIterator,即使大多数实现实际返回 ListIterator 实例。

类似的困境是EnumerationIterator。现在Iterator 将扩展Enumeration 并简单地添加remove() 方法。或者更好的是 Iterator 将替换 Enumeration 并添加一个 ModifiableIterator 额外的 remove()

【讨论】:

  • @ajb 看到你对 Dev too late 的回答的评论
【解决方案2】:

具体来说,它们都是必需的,因为ListIterable 的一种,它指定了Iterator iterator() 方法。

现在List 可以简单地覆盖Iterable 中的iterator() 方法来声明ListIterator 的返回类型,它是Iterator 的类型(从而满足合同)。为什么不这样做可能是一个设计决定。

编辑: @ajb 在评论中指出,协变返回类型是在创建 List 接口之后在 Java SE 5 中添加的。这就解释了为什么 List 有这两种方法,因为在 Java 1.2 中 iterator() 返回类型不能缩小到 ListIterator

【讨论】:

  • 可能是因为客户端必须将结果向下转换为 (ListIterator) 才能使用额外的 ListIterator 功能。
  • @ajb 您可以在子类型中编写覆盖方法,以便返回类型比在超类/接口中声明的类型返回更具体,并且编译器将接受它。这意味着如果您在上面的假设情况下使用List 作为List,则声明iterator() 返回ListIterator,您就不必沮丧。
  • 协变返回类型是在 1.5 中添加的,我想。 ListIterator 自 1.2 以来一直存在。
  • 对于它的价值,看起来AbstractSequentialListiterator() 方法只是return listIterator()。为什么AbstractListArrayList 不这样做,我不知道。看起来他们可以拥有。
  • @ajb 我不知道协变回报是一个附加功能。感谢您指出这一点,因为现在它很有意义。
【解决方案3】:

Java 的设计非常坚固——允许在不影响 Java 上运行的代码的情况下进行大量语言实现更改。

例如,您通常可以将“Java JRE 6”替换为“Java JRE 7”,并且大多数代码都不会出现问题——这是使用新语法和所有内容的整个语言升级。您还可以将 Java JRE 替换为开源实现,您将获得相同的结果 - 几乎可以正常工作。

所以当他们设计一个类时,他们必须同时为实现者和编码者设计它。

如果他们只是让一个 ArrayList 成为“Iterable”,那么对于 ArrayLists 返回一个 ListIterator 类型的 Iterator,那么接口将不需要另一个实现者(OpenJDK)来返回正确的类型——不仅如此,用户如果不查看文档,将不知道返回的是什么类型(如果每个人都以这种方式编程,Eclipse ctrl-space 将不太有用)。

Java 通常会尽量在物理上尽可能明确...这是一件非常好的事情,因为它停止猜测和相关错误。

当无法使接口和类型足够明确时,他们会非常谨慎地编写文档,但如果可能的话,他们会避免这样做。

【讨论】:

    【解决方案4】:

    Iterator 似乎用于单链表,ListIterator 用于双链表。

    【讨论】:

    • 如果是这样的话,它应该只是linkedlist类中的一个方法,而不是对此有接口。我的意思是它应该同时作用于arraylist和linkedlist,因为如果我的方法需要一个List,我可以传递arraylist或linkedlist
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-03
    • 2015-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-03
    • 1970-01-01
    相关资源
    最近更新 更多