List的引用数据类型的自定义排序以及TimSort的源码

本文以List>为例,详细介绍了如何按照Double由大到小进行排序。主要内容包括理解Comparator的compare方法,分析了JDK1.8中List接口的sort方法以及Arrays.sort的实现,特别是深入探讨了TimSort算法的工作原理,包括其对已排序段的查找、合并策略以及特殊情况的处理。最后通过示例展示了TimSort的排序过程。" 94859877,8669461,解决.NET Core中EF建模失败的问题,"['.NET开发', '数据库管理', '操作系统']
摘要由CSDN通过智能技术生成

1.例子

以List<Entry<String, Double>>为例
要求:按照Double由大到小来排序

Map<String, Double> map = new HashMap<String, Double>();
map.put("test2",2D);
map.put("test3",3D);
map.put("test1",1D);

List<Entry<String, Double>> mapList = new ArrayList<Entry<String, Double>>();
mapList.addAll(map.entrySet());

System.out.println(mapList);

Collections.sort(mapList, new Comparator<Entry<String, Double>>() {
    public int compare(Entry<String, Double> entry1, Entry<String, Double> entry2) {
    	Double d1 = entry1.getValue();
    	Double d2 =entry2.getValue();
        return d2.compareTo(d1);
    }
});
System.out.println(mapList);
}

打印结果为

[test2=2.0, test3=3.0, test1=1.0]
[test3=3.0, test2=2.0, test1=1.0]

主要需要注意下重写的compare方法的返回值,先看下Comparator.compare方法的调用的地方:

private static <T> void binarySort(T[] a, int lo, int hi, int start,
                                       Comparator<? super T> c) {
   assert lo <= start && start <= hi;
    if (start == lo)
        start++;
    for ( ; start < hi; start++) {
        T pivot = a[start];

        // Set left (and right) to the index where a[start] (pivot) belongs
        int left = lo;
        int right = start;
        assert left <= right;
        /*
         * Invariants:
         *   pivot >= all in [lo, left).
         *   pivot <  all in [right, start).
         */
        while (left < right) {
            int mid = (left + right) >>> 1;
            //在compare结果小于0的时候,会将pivot值排到a[mid]之前
            //反之,如果compare的结果大于等于0,会将pivot的值排到a[mid]之后
            if (c.compare(pivot, a[mid]) < 0)
                right = mid;
            else
                left = mid + 1;
        }
        assert left == right;

        /*
         * The invariants still hold: pivot >= all in [lo, left) and
         * pivot < all in [left, start), so pivot belongs at left.  Note
         * that if there are elements equal to pivot, left points to the
         * first slot after them -- that's why this sort is stable.
         * Slide elements over to make room for pivot.
         */
        int n = start - left;  // The number of elements to move
        // Switch is just an optimization for arraycopy in default case
        switch (n) {
            case 2:  a[left + 2] = a[left + 1];
            case 1:  a[left + 1] = a[left];
                     break;
            default: System.arraycopy(a, left, a, left + 1, n);
        }
        a[left] = pivot;
    }
}

2.源码

从最开始的Collections的sort排序方法开始看

public static <T> void sort(List<T> list, Comparator<? super T> c) {
    list.sort(c);
}

此方法直接调用了List接口的sort方法,从JDK1.8开始,接口已经可以写实现方法了。

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);
    }
}

其方法的本质还是调用了Arrays.sort(T[] a, Comparator<? super T> c)方法

public static <T> void sort(T[] a, Comparator<? super T> c) {
   if (c == null) {
        sort(a);
  
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值