2015-09-24 114 views
4

我有一個ArrayList,裏面填充了150萬個某些類的對象。當我通過使用Collection.sort方法對此列表進行排序時,JVM的分配內存會急劇增加。java的內存消耗Collection.sort()

所以我的問題是:

這是正常的嗎?這可能是什麼原因?這是垃圾收集器工作太慢還是不經常啓動的問題?列表中的對象是否必須滿足某些規範,以便在排序時消耗更少的內存(除了不包含那麼多的數據)?

THX!

+0

您可能需要考慮quicksort或heapsort或另一種通常比TIMSort更快的內存有效排序。 –

+0

Java 8或更舊的Java版本? – Seelenvirtuose

+0

您的班級是否實施「Comparable」或者您是否使用自定義的「Comparator」? 「compareTo」實現是什麼樣的? –

回答

4

爲了排序Listdefault sorting implementation首先創建要排序的所有元素的數組副本。這會導致您在排序時觀察到額外的堆消耗。這種複製是必要的,因爲通用的排序算法不知道列表的結構,例如,如果它是隨機訪問的。

對於Java 8,sorting implementation was however changed將被委派給List的每個實現。這使用默認方法成爲可能。對於ArrayList,通過實現更高效的排序算法,這個額外開銷could be removed。因此,升級到Java 8很可能會解決您的問題。

垃圾收集對於您的問題沒有任何問題。不幸的是,大型陣列很難處理,因爲它們可能不適合年輕一代,最終可能會引發全面收集。

此外,正如評論中提到的,實際的排序是performed via Tim Sort since Java 7Arrays::sort實現。 Tim排序需要額外的堆空間。從javadoc:

臨時存儲要求從幾乎排序的 輸入數組的小常量到隨機排序輸入數組的n/2個對象引用有所不同。

如果這並不適用於你的使用情況,您可以通過系統屬性java.util.Arrays.useLegacyMergeSort設置爲true切換回先前的合併排序的實現。

畢竟,蒂姆排序然而仍然比合並排序更有效,因爲合併排序需要另一個完整的數組副本。

+2

這個。這加上_「臨時存儲要求從幾乎排序的輸入數組的一個小常量到隨機排序的輸入數組的n/2個對象引用不同。」_這是Timsort對所有當前工作的sort()方法的實現說明 - 原始數據。 –