2013-10-24 75 views
12

我有一張地圖,我用這個地圖來存儲一旦創建(即使用;它們被快速消耗掉)的廢棄動態數據。它對用戶交互作出響應,當用戶點擊按鈕時,地圖被填充,然後數據用於做一些工作,然後不再需要地圖。地圖清除vs null

所以我的問題是清空地圖更好的方法是什麼?我應該每次都將它設置爲空,還是應該撥打clear()?我知道清楚是時間線性的。但我不知道如何比較每次創建地圖的成本。地圖的大小並不是恆定的,認爲它可能會在創作之間從n到3n個元素運行。

回答

7

如果未從其他可能難以設置新地圖的對象引用地圖,則簡單地輸出舊地圖並從頭開始可能比調用clear()更輕,因爲沒有線性地圖,時間清理需要發生。由於現代系統的垃圾收集成本很小,因此很有可能以這種方式節省一些CPU週期。您可以通過指定初始容量來避免多次調整地圖大小。

其中clear()是首選的一種情況是地圖對象在系統中的多個對象之間共享。例如,如果您創建地圖,將其提供給多個對象,然後在其中保留一些共享信息,則在所有這些對象中將地圖設置爲新地圖可能需要保持對具有該地圖的對象的引用。在這種情況下,在同一個共享地圖對象上繼續調用clear()更容易。

+0

從行中「例如,如果你創建一個映射,給它幾個對象......」你是否指通用映射(Map )? – Woody

+0

@Woody我的意思是創建一個實現'Map '接口的類,''HashMap '或者'TreeMap '。 – dasblinkenlight

+1

@Woody--我不明白爲什麼會這麼重要。他意味着如果有幾個對象引用了原始地圖,那麼您可能需要使用'clear()'來代替將地圖置零(將地圖的一個引用設置爲null將不會影響所有其他引用相同的地圖)。 – jahroy

2

嗯,這取決於你可以拋出多少內存。如果你有很多,那沒關係。但是,將映射本身設置爲null意味着您釋放了垃圾回收器 - 如果只有映射具有對其內部實例的引用,則垃圾回收器不僅可以收集映射,還可以收集其中的任何實例。 Clear會清空地圖,但它必須迭代地圖中的所有內容以將每個引用設置爲null,並且這會在您可以控制的執行時間內發生 - 無論如何,垃圾回收器本質上必須完成這項工作,所以讓它執行它的東西。請注意,將其設置爲null不會讓您重複使用它。重用映射變量的一個典型模式可能是:

Map<String, String> whatever = new HashMap<String, String(); 
// .. do something with map 
whatever = new HashMap<String, String>(); 

這樣您就可以重複使用變量,而不將其設置爲在所有空,你丟棄該參考舊地圖。在非內存託管的應用程序中,這是非常糟糕的做法,因爲它們必須引用舊指針來清除它(這是其他語言中的懸掛指針),但在Java中,因爲沒有引用此內容,所以GC將它標記爲符合收集條件。

+5

你的代碼片段不會編譯。你已經將引用聲明爲'final',所以你不能用一個構造函數重新指定它指向的內容。 – asteri

+1

雖然這是事實,但它不應該是一個downvote的原因(他可能寫了_final_出於習慣)。 – jahroy

+1

@jahroy同意。這不是什麼大事,他的觀點依然有效。只是指出了OP的好處。 – asteri

0

我覺得現有的地圖歸零比clear()便宜。由於在現代JVM中創建對象非常便宜。

0

簡短回答:使用Collection.clear(),除非它太複雜,以至於不能保持collection周圍。

詳細答案:在Java中,內存分配幾乎是瞬時的。它比在虛擬機內移動的指針多得多。但是,這些對象的初始化可能會增加一些重要的東西。而且,所有使用內部緩衝區的對象都適合調整大小和複製其內容。使用clear()確保緩衝區最終穩定到某個維度,以便重新分配內存並將舊緩衝區複製到新緩衝區時永遠不需要。

另一個重要的問題是重新分配然後釋放大量對象將需要更頻繁地執行垃圾收集器,這可能會導致突然滯後。

+1

@Woody請僅使用'code formatting'代碼,而不是強調。 –

+0

@Paul Bellora,謝謝我剛剛格式化了代碼並更正了印刷錯誤(「Grabage Collector to Garbage Collector」)。 – Woody

+1

是的,感謝修復,我正在從iPhone上寫信。對不起,錯別字。 – jwatkins

0

如果你總是拿着地圖,它會被提示給老一代。如果每個用戶都有一個相應的地圖,則舊一代的地圖數量與用戶數量成比例。當用戶數量增加時,它可能會更頻繁地觸發Full GC。

0

您可以使用這兩個類似的結果。

一個先前的答案指出clear預計在成熟的地圖實施中需要不變的時間。沒有檢查HashMap,TreeMap,ConcurrentHashMap之類的源代碼,我預計它們的clear方法需要不變的時間,加上amortized垃圾收集成本。

另一張海報指出,共享地圖不能被清空。好吧,如果你想要它,它可以,但是你可以通過使用封裝合適映射的對象來實現,並在需要時將其填充。當然,你必須自己實現代理映射類。

Map<Foo, Bar> myMap = new ProxyMap<Foo, Bar>(); 
    // Internally, the above object holds a reference to a proper map, 
    // for example, a hash map. Furthermore, this delegates all calls 
    // to the underlying map. A true proxy. 
myMap.clear(); 
    // The clear method simply reinitializes the underlying map. 

除非你不喜歡的東西上面,clear和歸零的出是在重要的方式相當,但我認爲這是比較成熟的假設您的地圖,即使目前不共享,有可能成爲在以後共享時間由於你無法預見的力量。

clear還有另外一個原因,即使映射未被共享,也不會歸零。您的地圖可能由外部客戶端實例化,如factory,所以如果您將地圖清零,您可能會自行結束coupling不必要的工作。爲什麼要清除地圖的對象必須知道你使用番石榴的Maps.newHashMap()實例化你的地圖,上帝知道什麼參數?即使這在您的項目中不是一個現實的問題,但它仍然有助於使自己適應成熟的實踐。

由於上述原因和其他條件相同,我會投票給clear

HTH。

+0

看起來'HashMap'的'clear'需要的時間與桶的數量成正比,根據負載的不同,這些桶可以是次線性的,超線性的或者線性的。 'TreeMap'具有一個常量時間'clear'方法。 'ConcurrentHashMap'更多地沿着'HashMap'的線。 –