源码剖析(二) Collections.sort 集合排序(List)

Collections.sort 这个方法使用了很多次了,剖析他的源码的意义很重要

1.实体类 (为了节省篇幅,大幅度削减)

public class Product {  
    private int productId;
}

2.排序使用 (下方为正序排序,逆序只需要return o2.getProductId() - o1.getProductId();)

Collections.sort(productList, new Comparator<Product>() {
            @Override
            public int compare(Product o1, Product o2) {
                return o1.getProductId() - o2.getProductId();
            }
});

3.sort方法源码

//第一步 调用list的sort方法
public static <T> void sort(List<T> list, Comparator<? super T> c) {
        list.sort(c);
}

//第二步 调用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);
        }
}

//第三步 传入比较器Comparator 调用TimSort.sort 方法
public static <T> void sort(T[] a, Comparator<? super T> c) {
        if (c == null) {
            sort(a);
        } else {
            //此排序将在未来版本删除
            if (LegacyMergeSort.userRequested)
                legacyMergeSort(a, c);
            else
                TimSort.sort(a, 0, a.length, c, null, 0, 0);
        }
}

4.TimSort.sort (排序所使用的算法)

TimSort 是一个归并排序做了大量优化的版本。对归并排序排在已经反向排好序的输入时做了特别优化。对已经正向排好序的输入减少回溯。对两种情况混合(一会升序,一会降序)的输入处理比较好。(来自百度百科)

查看源码发现,Timsort是结合了合并排序(merge sort)和插入排序(insertion sort)而得出的排序算法,它在使用中有很好的效率。

static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,
                         T[] work, int workBase, int workLen) {
        assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;

        int nRemaining  = hi - lo;
        if (nRemaining < 2)
            return;  // Arrays of size 0 and 1 are always sorted

        // If array is small, do a "mini-TimSort" with no merges
        if (nRemaining < MIN_MERGE) {
            int initRunLen = countRunAndMakeAscending(a, lo, hi, c);
            binarySort(a, lo, hi, lo + initRunLen, c);
            return;
        }

        /**
         * March over the array once, left to right, finding natural runs,
         * extending short natural runs to minRun elements, and merging runs
         * to maintain stack invariant.
         */
        TimSort<T> ts = new TimSort<>(a, c, work, workBase, workLen);
        int minRun = minRunLength(nRemaining);
        do {
            // Identify next run
            int runLen = countRunAndMakeAscending(a, lo, hi, c);

            // If run is short, extend to min(minRun, nRemaining)
            if (runLen < minRun) {
                int force = nRemaining <= minRun ? nRemaining : minRun;
                binarySort(a, lo, lo + force, lo + runLen, c);
                runLen = force;
            }

            // Push run onto pending-run stack, and maybe merge
            ts.pushRun(lo, runLen);
            ts.mergeCollapse();

            // Advance to find next run
            lo += runLen;
            nRemaining -= runLen;
        } while (nRemaining != 0);

        // Merge all remaining runs to complete sort
        assert lo == hi;
        ts.mergeForceCollapse();
        assert ts.stackSize == 1;
    }

 

<think>好的,用户想了解如何使用JavaCollections.sortList<String>进行排序。首先,我需要回忆一下相关知识。记得Collections.sort有两种常用的方法:一种是使用自然顺序排序,另一种是通过自定义比较器来排序。 根据引用[3],如果一个类实现了Comparable接口,就可以直接用Collections.sort进行自然排序。String类已经实现了Comparable,所以对于List<String>,直接调用Collections.sort(list)应该就能按字典序升序排列。那用户的问题应该包含这个方法的基本使用示例。 然后是降序排列。引用[1]提到可以使用Collections.sort(list, Collections.reverseOrder())来实现降序。这里需要传入一个比较器,reverseOrder()会返回一个逆序的比较器。因此,在示例中应该展示这两种情况:升序和降序。 接下来要考虑代码的正确性。例如,示例中的List<String>是否正确初始化,排序后的输出是否符合预期。可能需要先创建一个包含无序字符串的列表,然后分别调用两种排序方法,并打印结果。 还要注意用户可能的疑问,比如是否区分大小写。因为String的默认排序是区分大小写的,大写字母会排在小写字母前面。如果用户需要不区分大小写的排序,可能需要自定义比较器,比如使用String.CASE_INSENSITIVE_ORDER。虽然用户的问题中没有提到这点,但作为相关知识可以补充在相关问题里。 另外,引用[2]提到两种方法的源码,可能涉及到比较器的使用。比如,第个方法需要传入自定义的Comparator,这可能用于更复杂的排序需求,但用户的问题主要集中在List<String>,所以暂时不需要深入这部分,但可以作为扩展知识提及。 最后,根据用户提供的引用,特别是引用[1]中的例子,需要确保代码示例的正确格式,比如使用正确的泛型语法,避免尖括号被转义。在回答中使用代码块,并正确显示List<String>的类型声明。 总结步骤:首先介绍自然排序(升序),然后降序,提供代码示例,解释各部分的作用,并补充可能的注意事项,如大小写问题。最后生成相关问题,帮助用户进一步学习。</think>### 使用 `Collections.sort` 对 `List<String>` 排序的示例 #### 1. **默认升序排序** 直接调用 `Collections.sort(list)`,按字符串的**字典序**(自然顺序)升序排列: ```java List<String> list = new ArrayList<>(); list.add("apple"); list.add("Banana"); list.add("cherry"); list.add("1_apple"); // 升序排序(字典序) Collections.sort(list); System.out.println("升序结果:" + list); // 输出:[1_apple, Banana, apple, cherry] ``` - **说明**:排序规则为 Unicode 值比较,数字 < 大写字母 < 小写字母[^3]。 --- #### 2. **降序排序** 通过 `Collections.reverseOrder()` 指定降序比较器: ```java // 降序排序(字典序反向) Collections.sort(list, Collections.reverseOrder()); System.out.println("降序结果:" + list); // 输出:[cherry, apple, Banana, 1_apple] ``` --- #### 3. **自定义排序规则(如忽略大小写)** 若需忽略大小写排序,可使用 `String.CASE_INSENSITIVE_ORDER` 比较器: ```java // 不区分大小写的升序 Collections.sort(list, String.CASE_INSENSITIVE_ORDER); System.out.println("不区分大小写升序:" + list); // 输出:[1_apple, apple, Banana, cherry] ``` --- ### 关键注意事项 1. **原列表被修改**:`Collections.sort` 直接修改原列表,而非返回新列表[^1]。 2. **排序稳定性**:对 `List<String>` 的排序是稳定的(相等元素顺序不变)。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值