我正在尝试使用List
界面创建循环链表实现,并注意到一个有趣的副作用。
虽然CircularLinkedList
满足List合约,但它打破了
其他当前实施的collection
类!
问题是这个 - ListIterator接口提供以下内容 hasNext()和hasPrevious()方法的合同:
public boolean hasNext()
如果此列表迭代器具有更多元素,则返回true 在前进方向遍历列表。 (换句话说,回报 如果next将返回一个元素而不是抛出异常,则为true。)
public boolean hasPrevious()
如果此列表迭代器具有更多元素,则返回true 以相反的方向遍历列表。 (换句话说,回报 如果previous返回一个元素而不是抛出异常,则为true。)
现在在循环列表中,当且仅当List为空时,合同中的每一个都应该返回 false 。
当您尝试使用 addAll()方法将具有相应列表迭代器的循环列表添加到另一个Collection时,问题就会出现 - 该方法使用 hasNext()在添加每个元素时约束迭代。因此 循环永远不会终止!
我目前正在考虑违反ListIterator的合同,如果您正在查看hasNext()方法,则使列表看起来像链接列表,或者创建迭代器的子类,并重写hasNext以返回iterator()方法。
两个问题:
在不破坏迭代器的情况下,有更好的方法吗? 或ListIterator合同?
是否有其他人认为这是AbstractCollection类(继承行为来自哪里)的缺陷。请注意,某些集合通过调用要添加的集合的toArray()方法并添加数组的每个元素,以更强大的方式执行添加。
答案 0 :(得分:1)
在我看来,这既不是 Collections API 中的缺陷,也不是定义hasNext
和hasPrevious
方法的合同的方式。
问题在于您对循环列表的思考方式:
hasNext
和hasPrevious
并不重要。排序只定义何时返回哪个元素。如果你的迭代器返回相同的元素(根据列表中的绝对位置的身份),那么你的迭代器实现是错误的。
您必须将如何从列表中包含的元素数量中排序元素的想法分离出来。列表中元素的数量由size
的结果定义。因此,如果仅向前导航,hasNext
应该true
完全size
次回答。在hasPrevious
获得false
作为答案后向后导航时,hasNext
也是如此。