浅析Java集合中的排序算法

本文深入剖析Java集合排序,重点关注Collections.sort()使用的TimSort算法,探讨其核心思想和优势,包括二分插入排序、自适应特性与归并排序的融合。同时,介绍了DivalQuickSort算法,展示双轴快排的原理。通过对两种排序算法的分析,强调工业级排序算法通常是多种策略结合的产物,启发开发者深入理解常用数据结构和算法的实现细节。
摘要由CSDN通过智能技术生成

1.  引言

排序是一个Java开发者,在日常开发过程中随处可见的开发内容,Java中有丰富的API可以调用使用。在Java语言中,作为集合工具类的排序方法,必定要做到通用、高效、实用这几点特征。使用什么样排序算法会比较合适,能够做到在尽量降低时间、空间复杂度的情况下,又要兼顾保证稳定性,达到优秀的性能。可能从性能角度出发首先会想到的是快速排序,或者归并排序。作为jdk提供的通用排序功能,使用又如此频繁,肯定有独特之处,一起来看学习下期中的奥秘。

文中不会过多的介绍几大基本排序算法的方式、由来和思想,主要精力集中在一块探讨java中排序方法所使用的算法,以及那些是值得我们学习和借鉴的内容。文中如有理解和介绍的错误,一起学习,一起探讨,一起进步。

2.  案例

日常使用最为频繁的排序,莫过于如下代码案例,给定一个现有的序列进行一定规则下的排序,配合java8的stream特性,可以很方便的对一个集合进行排序操作(排序规则只是对排序对象及排序方案的限定,不在本文讨论范围内)。

List<Integer> list = Arrays.asList(10, 50, 5, 14, 16, 80);
System.out.println(list.stream().sorted().collect(Collectors.toList()));

在代码执行的过程中SortedOps.java类中 Arrays.sort(array, 0, offset, comparator); 执行了Array集合类型的sort排序算法。

@Override
public void end() {
    Arrays.sort(array, 0, offset, comparator);
    downstream.begin(offset);
    if (!cancellationWasRequested) {
        for (int i = 0; i < offset; i++)
            downstream.accept(array[i]);
    }
    else {
        for (int i = 0; i < offset && !downstream.cancellationRequested(); i++)
            downstream.accept(array[i]);
    }
    downstream.end();
    array = null;
}

如果使用Collections.sort() 方法如下打印 list1 和 list2 结果一样,且调用的都是 Arrays 集合类中的 sort 方法。

List<Integer> list1 = Arrays.asList(10, 50, 5, 14, 16, 80);
System.out.println(list1.stream().sorted().collect(Collectors.toList()));

List<Integer> list2 = Lists.newArrayList();
list2.addAll(list1);
Collections.sort(list2);
System.out.println(list2);
// 输出:
// [5, 10, 14, 16, 50, 80]
// [5, 10, 14, 16, 50, 80]

2.  Collections.sort 方法介绍

Collections类中关于sort方法定义如下:

public static <T extends Comparable<? super T>> void sort(List<T> list) {
    list.sort(null);
}

通过该方法注释,查看到有三项值得关注的信息,大概意思是该方法实现了稳定且默认升序排序的功能。

1. Sorts the specified list into ascending order, according to the Comparable natural ordering of its elements.
2. This sort is guaranteed to be stable equal elements will not be reordered as a result of the sort.
3. The specified list must be modifiable, but need not be resizable.

进入sort,代码进入到List类的sort方法,发现方法将入参list先转为了数组Object[],之后利用Arrays.sort进行排序。

default void sort(Comparator<? super E> c) {
    Object[] a = this.toArray();
    Arrays.sort(a, (Comparator) c);
    ListIterator<E> i = this.listIterator();
    for (Object e : a) {
        i.next();
        i.set((E) e);
    }
}

首先在这里思考一个问题为什么要转为数组,问题答案已经在方法的英文注释中说明白了。

* The default implementation obtains an array containing all elements in
* this list, sorts the array, and iterates over this list resetting each
* element from the corresponding position in the array. (This avoids the
* n<sup>2</sup> log(n) performance that would result from attempting
* to sort a linked list in place.)

是为了避免直接对List的链表进行排序,从而耗费O(n2logn) 时间复杂度。当然这里在this.toArray()时,为了将list强行变为数组会损失一些性能和空间开销,源码中使用了System.arraycopy调用底层操作系统方法进行数据复制,详细内容可以查看相关实现。 继续进入Arrays类的sort方法定义中,我们没有使用比较器,Leg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值