ver*_*ern 5 java memory sorting collections heap-memory
我有一个 ArrayList 填充了某个类的 150 万个对象。当我使用 Collection.sort 方法对这个列表进行排序时,JVM 的分配内存急剧增加。
所以我的问题是:
这是正常的吗?这可能是什么原因?这是垃圾收集器工作太慢还是没有经常启动的问题?列表中的对象是否必须满足某些规范才能在排序期间消耗更少的内存(除了不包含那么多数据)?
谢谢!
为了对 a 进行排序List,默认排序实现首先创建要排序的所有元素的数组副本。这会导致您在排序时观察到额外的堆消耗。这种复制是必要的,因为通用排序算法不知道列表的结构,例如它是否是随机访问的。
然而,对于 Java 8,排序实现已更改为委托给List. 通过使用默认方法,这成为可能。对于,可以通过实现更有效的排序算法来消除ArrayList这种额外的开销。因此,升级到 Java 8 很可能会解决您的问题。
对于您的问题,垃圾收集没有任何问题。不幸的是,大型数组处理起来很繁重,因为它们可能不适合年轻一代,并且最终会触发完整的收集。
此外,正如评论中提到的,自 Java 7 以来,实际的排序是通过Tim Sort实现的Arrays::sort。蒂姆排序需要额外的堆空间。来自javadoc:
临时存储要求各不相同,从几乎排序的输入数组的小常量到随机排序的输入数组的 n/2 对象引用。
java.util.Arrays.useLegacyMergeSort如果这不适用于您的用例,您可以通过将系统属性设置为 来切换回以前的合并排序实现true。
毕竟,蒂姆排序仍然比合并排序更有效,因为合并排序需要另一个完整的数组副本。