java Collection.sort() 的内存消耗
Memory consumption of java Collection.sort()
我有一个 ArrayList,其中包含一些 class 的 150 万个对象。当我使用 Collection.sort 方法对这个列表进行排序时,分配给 JVM 的内存急剧增加。
所以我的问题是:
这正常吗?这可能是什么原因?这是垃圾收集器工作太慢或启动不够频繁的问题吗?列表中的对象是否必须满足某些规范才能在排序期间消耗更少的内存(除了不包含那么多数据)?
谢谢!
为了对 List
进行排序,default sorting implementation 首先创建要排序的所有元素的数组副本。这会导致您在排序时观察到额外的堆消耗。这种复制是必要的,因为通用排序算法不知道列表的结构,例如它是否是随机访问。
对于Java 8、sorting implementation was however changed to be delegated to each implementation of a List
. This became possible with using default methods. For an ArrayList
, this additional overhead could be removed通过实现更高效的排序算法。因此,升级到 Java 8 很可能会解决您的问题。
对于您的问题,垃圾回收没有任何问题。不幸的是,大型数组很难处理,因为它们可能不适合年轻一代,最终会触发完整的收集。
此外,如评论中所述,实际排序是由 Arrays::sort
实现的 performed via Tim Sort since Java 7。 Tim sort 需要额外的堆 space。来自 javadoc:
Temporary storage requirements vary from a small constant for nearly sorted
input arrays to n/2 object references for randomly ordered input arrays.
如果这不适用于您的用例,您可以通过将系统 属性 java.util.Arrays.useLegacyMergeSort
设置为 [=15= 来切换回以前的合并排序实现].
毕竟,Tim 排序 仍然比合并排序更有效,因为合并排序需要另一个完整的数组副本。
我有一个 ArrayList,其中包含一些 class 的 150 万个对象。当我使用 Collection.sort 方法对这个列表进行排序时,分配给 JVM 的内存急剧增加。
所以我的问题是:
这正常吗?这可能是什么原因?这是垃圾收集器工作太慢或启动不够频繁的问题吗?列表中的对象是否必须满足某些规范才能在排序期间消耗更少的内存(除了不包含那么多数据)?
谢谢!
为了对 List
进行排序,default sorting implementation 首先创建要排序的所有元素的数组副本。这会导致您在排序时观察到额外的堆消耗。这种复制是必要的,因为通用排序算法不知道列表的结构,例如它是否是随机访问。
对于Java 8、sorting implementation was however changed to be delegated to each implementation of a List
. This became possible with using default methods. For an ArrayList
, this additional overhead could be removed通过实现更高效的排序算法。因此,升级到 Java 8 很可能会解决您的问题。
对于您的问题,垃圾回收没有任何问题。不幸的是,大型数组很难处理,因为它们可能不适合年轻一代,最终会触发完整的收集。
此外,如评论中所述,实际排序是由 Arrays::sort
实现的 performed via Tim Sort since Java 7。 Tim sort 需要额外的堆 space。来自 javadoc:
Temporary storage requirements vary from a small constant for nearly sorted input arrays to n/2 object references for randomly ordered input arrays.
如果这不适用于您的用例,您可以通过将系统 属性 java.util.Arrays.useLegacyMergeSort
设置为 [=15= 来切换回以前的合并排序实现].
毕竟,Tim 排序 仍然比合并排序更有效,因为合并排序需要另一个完整的数组副本。