
Java中的
Collections.sort
TimSort的原理并不算特别复杂,但其设计哲学却相当精妙。它首先会遍历待排序的列表,寻找其中已有的“自然升序或降序”的子序列,这些子序列被称为“run”。如果一个run的长度小于某个预设的最小值(min-run),TimSort会使用插入排序来扩展它,直到达到min-run的长度。插入排序在小规模数据上表现极佳,且开销很小。一旦所有run都被识别并调整到合适的长度,TimSort就会进入归并阶段。它会以一种智能的方式,将相邻的run两两合并,直到整个列表有序。这个合并过程是稳定的,也就是说,如果两个元素相等,它们在排序后的相对位置不会改变。这种“先局部优化,再全局整合”的策略,使得TimSort在各种数据分布下都能保持出色的性能。
TimSort之所以能在各种数据规模下都保持高效,主要得益于它的自适应性。它不像纯粹的归并排序那样,无论数据状况如何都进行机械的分割和合并;也不像纯粹的快速排序那样,在最坏情况下性能急剧下降。TimSort的第一个关键优化在于识别并利用数据中已有的有序性。它会寻找自然形成的“run”,如果数据已经部分有序,这些run会很长,从而减少了需要排序的工作量。
另一个关键点是那个“min-run”的概念。这个值通常是32或64,根据列表大小动态计算。当找到的run短于min-run时,TimSort会用插入排序将其扩展到min-run的长度。插入排序在处理小规模数据时,缓存命中率高,常数因子小,效率反而比归并排序更高。这就像是,对于一堆散落的小物件,你用手快速整理比用大型机械搬运要快得多。
立即学习“Java免费学习笔记(深入)”;
在合并阶段,TimSort也做了很多优化。它并不是简单地将两个run合并,而是使用了一个“栈”来管理待合并的run,并应用了一些启发式规则(如galloping模式),以减少比较次数和内存移动。例如,当一个run中的元素明显小于另一个run中的元素时,它可以快速地将整个run移动到结果中,而不需要逐个比较。这种设计让它在处理几乎有序、随机或者逆序的数据时,都能有不错的表现。我个人觉得,这种混合策略是算法设计中的一种艺术,它结合了不同算法的优点,以适应更广泛的实际应用场景。
当我们需要对自定义对象列表进行排序时,
Collections.sort
Comparable
Comparator
如果你的自定义对象本身就有一种“自然排序”的逻辑,比如按ID升序,或者按名称字母顺序,那么最好的方式是让这个类实现
Comparable<T>
compareTo(T o)
public class Product implements Comparable<Product> {
private String name;
private double price;
// 构造函数、getter略
@Override
public int compareTo(Product other) {
// 默认按价格升序排序
return Double.compare(this.price, other.price);
}
}这样,你就可以直接调用
Collections.sort(productList)
Product
但有时候,一个对象可能需要多种排序方式(比如按价格、按名称、按库存等),或者你无法修改类的源代码(例如,它是一个第三方库的类)。这时候,
Comparator<T>
Comparator
Collections.sort
Collections.sort(list, comparator)
// 使用Lambda表达式按名称排序 Collections.sort(productList, (p1, p2) -> p1.getName().compareTo(p2.getName())); // 或者按价格降序排序 Collections.sort(productList, (p1, p2) -> Double.compare(p2.getPrice(), p1.getPrice()));
在我看来,最容易犯的错误就是
compareTo
compare
a.compareTo(b)
b.compareTo(a)
a.compareTo(b)
a.equals(b)
IllegalArgumentException
Collections.sort
Arrays.sort
最显著的共同点是,对于对象类型的数组或列表,它们都倾向于使用TimSort算法。无论是
Collections.sort(List<T> list)
Arrays.sort(Object[] a)
然而,差异主要体现在对原始数据类型(如
int[]
long[]
char[]
Collections.sort
List
List
int
Collections.sort
List<Integer>
Arrays.sort
Arrays.sort(int[] a)
Arrays.sort(long[] a)
Arrays.sort
所以,在我看来,这是Java在设计时的一个实用性考量:
Collections.sort
Arrays.sort
简单来说,如果你处理的是
List
Collections.sort
Arrays.sort
以上就是Java中Collections.sort方法的原理的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号