簡體   English   中英

關於清除鏈接列表的Java最佳實踐

[英]Java Best Practice regarding clearing a Linked List

我正在編寫一個數據結構java中的鏈表(為了我的學習,我沒有使用任何標准的java庫),我想通過null引用清除數據結構。 請建議我哪種方法更好

1)只需清空列表的開始引用即可。

2)除了取消啟動之外,我將所有內部節點的所有下一個指針取消引用為null。這有助於垃圾收集器嗎?

我看到方法2的混亂在JDK中遵循LinkedList實現。但是我沒有看到相同的TreeMap

我使用的是JDK 8

這是一個有趣的問題,答案歷史悠久,有微妙的權衡。

簡而言之,清除引用對於正確操作數據結構不是必需的。 由於您正在學習數據結構,我建議您不要在自己的實現中擔心這個問題。 我的預感(雖然我沒有對此進行基准測試)是在清除所有鏈接節點時可能產生的任何好處在典型條件下很少會引起注意。

(另外,很可能是典型的條件下, LinkedList將被跑贏ArrayListArrayDeque 。有跡象表明,說明這個標准。這不是太難拿出其中的工作量LinkedList優於別人,但它是罕見的比人們想象的。)

我很驚訝地發現LinkedListclear操作將所有節點彼此clear鏈接並從所包含的元素clear鏈接。 這是JDK 8中代碼的鏈接。 此更改可以追溯到2003年,更改出現在JDK 5中。此更改由JDK-4863813錯誤跟蹤。 當從列表中取消鏈接時,該更改(或稍早的更改)將清除單個節點的下一個和上一個引用。 在該bug報告中還有一個測試案例,它有一些興趣。

問題似乎是可以對LinkedList進行更改,這會創建垃圾節點,比垃圾回收器可以回收它們更快。 這最終會導致JVM內存不足。 垃圾節點全部鏈接在一起的事實似乎也具有阻止垃圾收集器的效果,使得mutator線程更容易超過收集器線程。 (我不清楚讓多個線程改變列表是多么重要。在測試用例中,它們都在列表上同步,因此沒有實際的並行性。)對LinkedList的更改以使節點彼此取消鏈接使得它更容易讓收集器完成它的工作,因此顯然使測試不再耗盡內存。

快進到2009年,當LinkedList代碼被賦予“整容”。 這是由錯誤JDK-6897553跟蹤,並在此電子郵件審查主題中進行了討論。 “整容”的原始動機之一是將clear()操作從O(n)減少到O(1),因為取消鏈接所有節點對於該bug的提交者來說似乎是不必要的。 (這對我來說當然沒必要!)但經過一些討論后,決定取消鏈接行為為垃圾收集器提供足夠的好處以保留它並記錄它。

評論還說取消了節點的鏈接

即使有可達的迭代器,也一定要釋放內存

這指的是一個有點病態的情況,如下所示:

// fields in some class
List<Obj> list = createAndPopulateALinkedList();
Iterator<Object> iterator;

void someMethod() {
    iterator = list.iterator();
    // ...
    list.clear();
}

迭代器指向鏈表的一個節點。 即使列表已被清除,迭代器仍然使節點保持活動狀態,並且由於該節點具有下一個和先前的引用,因此以前在列表中的所有節點仍然存活。 取消鏈接clear()所有節點可以收集這些節點。 我認為這是非常病態的,因為迭代器很少存儲在字段中。 通常,迭代器在單個方法中創建,使用和丟棄,通常在單個for循環中。

現在,關於TreeMap 我不認為LinkedList取消鏈接其節點的根本原因,而TreeMap沒有。 有人可能會認為整個JDK代碼庫是一致的,所以如果LinkedList取消鏈接節點是一個好習慣,那么TreeMap也應該這樣做。 唉,事實並非如此。 最有可能發生的事情是客戶遇到了使用LinkedList的病態行為,並且在那里進行了更改,但沒有人觀察到與TreeMap類似的行為。 因此,沒有動力更新TreeMap

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM