Java:就地对 ArrayList 进行排序

Posted

技术标签:

【中文标题】Java:就地对 ArrayList 进行排序【英文标题】:Java: sorting an ArrayList in place 【发布时间】:2011-12-20 06:33:26 【问题描述】:

在 Java 的标准库中,是否有一种方法可以就地对 ArrayList 进行排序,即使用 O(1) 额外存储空间?

Collections.sort(List<T>) 不满足此要求,因为它

将指定的列表转储到一个数组中,对数组进行排序,然后遍历列表,从数组中的相应位置重置每个元素。

如果标准库中什么都没有,有哪些第三方库可以做到这一点?

【问题讨论】:

【参考方案1】:

从 Java 8 开始,List 接口具有默认的void sort(Comparator<? super E> c) API,您可以使用它对实例进行就地排序。

列表必须是可修改的、可迭代的,并且它的元素可以相互比较。

【讨论】:

【参考方案2】:

Collections.sort() 可以与任何 List 实现一起使用,这就是它无法正常工作的原因(合并 LinkedList 很困难并且会牺牲稳定性)。

如果您真的担心就地排序,则必须推出自己的排序功能。除非您的列表很长,否则不值得您花时间。

Arrays.sort(Object[]) 执行相同的归并排序,并由Collections.sort() 内部调用(至少在 openjdk 中)

【讨论】:

您可以使用 ArrayList 而不是数组来复制此处描述的堆排序:[link]en.wikibooks.org/wiki/Algorithm_Implementation/Sorting/Heapsort)【参考方案3】:

您可以提取底层数组(例如反射)并对其执行 Arrays.sort(array, 0, list.size())。

Java 7 在对数组进行排序之前不会复制 Arrays.sort() 中的数组。在 Java 6 中,这意味着 Java 6 中的 Collections.sort() 实际上复制了底层数组 TWICE 来执行排序。

【讨论】:

唯一的事情是这需要一个数组的副本,因此根据 Collections.sort 使用 O(n) 额外存储。 在 Java 7 中不需要复制。我还没有检查过 Java 6。 有趣。我真的很惊讶他们改变了返回底层数组的行为;可以想象这会给从 Java 6 升级的人带来很多微妙的错误。 Arrays.sort() 不返回任何内容。问题是它是否在排序之前复制数组。 在 Java 8 中 Collections.sort 调用列表上的 sort,所以这取决于列表实现。 ArrayList 使用其元素数组调用 Arrays.sort,所以它仍然存在。

以上是关于Java:就地对 ArrayList 进行排序的主要内容,如果未能解决你的问题,请参考以下文章

Java:如何按大小对多个 ArrayList 进行排序?

对 Java ArrayList 的一部分进行排序

如何就地对文件进行排序

Java对ArrayList进行排序

java - 如何对对象的arraylist进行排序?

在 Java 8 中使用 Lambda 对 ArrayList 进行排序