2017-04-24 35 views
1

我試圖使用List接口創建一個循環鏈表實現,並且已經注意到一個有趣的副作用。循環鏈表和迭代器API缺乏確定性

儘管CircularLinkedList滿足列表合同,但它打破了 其他目前實施的collection類!

問題是這樣的 - 在的ListIterator接口提供了以下 合同的hasNext()和hasPrevious()方法:

公共布爾hasNext()

返回true,如果這個名單當 正向遍歷列表時,迭代器具有更多元素。如果列表迭代器有多個元素(換句話說,返回 true,如果next返回一個元素而不是拋出異常。)

公共布爾hasPrevious()

返回true時 遍歷列表在相反的方向。 (換句話說,返回 true,如果以前將返回一個元素而不是拋出異常。)

現在,在循環列表,每一個這些應該由合同返回,當且僅當列表是空的。

的問題表現出來了,當你嘗試用適當的列表迭代器增加一個循環鏈表使用中的addAll()方法的另一個系列 - 該方法使用hasNext()來約束迭代,因爲它增加了每個元素。因此 循環永遠不會終止!

我目前正在考慮打破ListIterator的合同,如果您正在查看hasNext()方法或使用hasNext覆蓋來創建迭代器的子類,則使列表看起來像鏈接列表通過iterator()方法。

兩個問題:

  1. 是否有這樣做沒有打破迭代 的ListIterator或合同的更好的辦法?

  2. 是否有人認爲這是AbstractCollection類中的一個缺陷(這是繼承行爲的來源)。請注意,某些集合通過調用要添加的集合的toArray()方法並添加數組的每個元素來以更穩健的方式執行添加。

回答

1

在我看來,這是既不在集合API也不在的方式存在缺陷兩種方法hasNexthasPrevious合同的定義。

問題從你想想你的循環鏈表的方式蒸:

  • 列表有元素的固定大小,因此一個迭代器應該能夠對它們進行排序,其中有一個起點和方式結束。
  • 不管你如何在列表中組織你的元素來回答hasNexthasPrevious。排序只確定何時返回哪個元素。

如果你的迭代器返回相同的元素(在你的列表中絕對位置的身份),那麼你的迭代器實現是錯誤的。

你必須從你的列表包含的元素中分解出如何排列元素的想法。列表中元素的數量由size的結果定義。因此,如果僅導航前進,hasNext應與true正好size次。在獲得false作爲hasNext的回答後向後導航時,hasPrevious也是如此。