关于Comparable、Comparator接口返回值决定顺序的问题

这篇具有很好参考价值的文章主要介绍了关于Comparable、Comparator接口返回值决定顺序的问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Comparable和Comparator接口都是实现集合中元素的比较、排序的,下面先简单介绍下他们的用法。

1. 使用示例

public class Person {

	private String name;
	private Integer age;
	public Person() {}
	public Person(String name, Integer age) {
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Person{" +
				"name='" + name + '\'' +
				", age=" + age +
				'}';
	}

	@Override
	public int compareTo(Person o) {
		return  this.age - o.age;
	}
}
        ArrayList<Person> list = new ArrayList<>();

        list.add(new Person("朱一百",100));
        list.add(new Person("朱八零",80));
        list.add(new Person("朱八一",81));
        list.add(new Person("朱九零",90));
        list.add(new Person("朱八二",82));
        list.add(new Person("朱七七",77));
        list.add(new Person("朱八八",88));
        list.add(new Person("朱重八",88));

1.1 Comparable

public class Person  implements Comparable<Person>{
	......
    @Override
    public int compareTo(Person o) {
        if (this.getAge() < o.getAge()) {
            return -1;
        } else if (this.getAge() > o.getAge()) {
            return 1;
        } else {
            return this.getName().compareTo(o.getName());
        }
    }
}
public class ComparableTest {
    public static void main(String[] args) {
    	......
        Collections.sort(list);
        list.forEach(System.out::println);
    }
}

1.2 Comparator

public class PersonComparator  implements Comparator<Person> {
    @Override
    public int compare(Person o1, Person o2) {
        if (o1.getAge() < o2.getAge()) {
            return -1;
        } else if (o1.getAge() > o2.getAge()) {
            return 1;
        } else {
            return o1.getName().compareTo(o2.getName());
        }
    }
}
public class ComparatorTest {
    public static void main(String[] args) {
    	......
        Collections.sort(list,new PersonComparator());
        list.forEach(System.out::println);
    }
}

以上的两个例子输出的结果如下所示:

Person{name='朱七七', age=77}
Person{name='朱八零', age=80}
Person{name='朱八一', age=81}
Person{name='朱八二', age=82}
Person{name='朱八八', age=88}
Person{name='朱啊八', age=88}
Person{name='朱九零', age=90}
Person{name='朱一百', age=100}

按照年龄升序排列,年龄相同时按照姓名升序排序。

2. 关于返回结果-1 0 1 和排序的关系

在上面的例子中我们分别实现了compare()compareTo()对集合继续宁排序,但是我们想知道方法返回-1、0、1对集合排序的关系。

2.1 Comparable

List#sort() =>ArrayList#sort() => Arrays#sort() ⇒ ComparableTimSort#sort() ⇒ ComparableTimSort.#countRunAndMakeAscending()
关于Comparable、Comparator接口返回值决定顺序的问题,java
可以看到到Comparator c == null 时进入sort() 方法,当我们实现Comparator进行排序时,进入的方法就应该是 TimSort.sort()
关于Comparable、Comparator接口返回值决定顺序的问题,java
关于Comparable、Comparator接口返回值决定顺序的问题,java
关于Comparable、Comparator接口返回值决定顺序的问题,java
countRunAndMakeAscending方法如下:

    private static int countRunAndMakeAscending(Object[] a, int lo, int hi) {
        assert lo < hi;
        int runHi = lo + 1;
        if (runHi == hi)
            return 1;
        
        if (((Comparable) a[runHi++]).compareTo(a[lo]) < 0) { // Descending
            while (runHi < hi && ((Comparable) a[runHi]).compareTo(a[runHi - 1]) < 0)
                runHi++;
            reverseRange(a, lo, runHi);
        } else {                              // Ascending
            while (runHi < hi && ((Comparable) a[runHi]).compareTo(a[runHi - 1]) >= 0)
                runHi++;
        }

        return runHi - lo;
    }

如果当前子序列是"递减"的,也就是 a[runHi] 小于 a[lo],那么需要找到连续"递减"的子序列的结束位置 runHi。直到找到第一个不满足"递减"条件的元素。然后,调用 reverseRange 方法将"递减"的子序列反转为"递增"的子序列。

如果当前子序列是"递增"的,也就是 a[runHi] 大于等于 a[lo],那么需要找到连续"递增"的子序列的结束位置 runHi。
最后,返回 runHi - lo,即子序列的长度。

    private static void binarySort(Object[] a, int lo, int hi, int start) {
        assert lo <= start && start <= hi;
        if (start == lo)
            start++;
        for ( ; start < hi; start++) {
            Comparable pivot = (Comparable) a[start];

            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;
                // pivot元素的索引比a[mid]的索引大
                // pivot元素在数组中比a[mid]靠后
                if (pivot.compareTo(a[mid]) < 0)
                    right = mid;
                else
                    left = mid + 1;
            }
            assert left == right;
            
            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;
        }
    }

这个方法做的事情如下:

  1. 经过countRunAndMakeAscending()方法 start位置之前的集合是有序的,于是start位置开始,pivot=array[start],使用二分查找法对start之前已经有序的数组比对,从start下标开始从后往前找,找到start下标之前第一个大于array[start]的元素下标index;
  2. 根据要移动的步数n = start - left做了优化,但是目的是将[left, start-1]范围内的数组值都向后移动一位,放在 [left+1~start],再把pivot的值赋予array[left];
  3. start++,循环执行以上步骤直到数组结束

总结

我们实现的compareTo()方法返回-1 0 1 和集合的排序是升序或者降序没有直接的关系,在上面的方法我们可以看到的是compareTo()返回会导致如下结果:

  1. 返回-1说明两个比较的元素需要交换位置
  2. 但会0或者1不需要交换两个元素的位置

所以我们应该能比较清楚的知道返回-1 0 1 给我们排序带来的效果了,比如上方的pivot.compareTo(a[mid]) pivot在数组中比a[mid]靠后,当 if (this.getAge() < o.getAge()) {return -1}; 我们希望pivot的age小于a[mid]时交换位置,最后排序的结果就是年龄的升序,如果if (this.getAge() < o.getAge()) {return 1};最后排序的结果就是年龄的降序文章来源地址https://www.toymoban.com/news/detail-694362.html

到了这里,关于关于Comparable、Comparator接口返回值决定顺序的问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 关于Promise.all 传入promose实例数组和返回值res数组元素的顺序问题

    第一个promise返回结果比第二个慢点,但是返回的结果还是在第一个元素里 所以res数组里面的元素顺序和传入的promise实例数组的元素顺序是一致的

    2024年02月06日
    浏览(39)
  • java~搞懂Comparable接口的compareTo方法

    Comparable 接口的 compareTo 方法的升序或降序取决于实现该接口的类的具体实现。按照惯例, compareTo 方法应该返回负数、零或正数来指示当前对象是小于、等于还是大于传入的对象。具体来说: 如果 this 对象小于传入的对象,则 compareTo 应该返回负数。 如果 this 对象等于传入的

    2024年02月09日
    浏览(40)
  • 内置函数式接口-Comparator

    【 美 /ˈkɑːmpəˌreɪtər; kəmˈpærətər/】 比较器 Compares its two arguments (o1,o2) for order,Returns a integer。 1、 negative integer, first argument is less than the second → 0 o1o2 2、 zero, first argument i, equal to than the second → =0 o1=o2 3、 positive integer ,first argument is greater than the second → 0 o1o2

    2024年02月15日
    浏览(32)
  • 【Java 基础篇】Java 自然排序:使用 Comparable 接口详解

    在 Java 编程中,我们经常需要对对象进行排序。为了实现排序,Java 提供了 java.lang.Comparable 接口,它允许我们定义对象之间的自然顺序。本篇博客将深入探讨如何使用 Comparable 接口来进行自然排序,包括接口的基本概念、使用示例以及一些常见问题的解决方法。 自然排序是一

    2024年02月04日
    浏览(39)
  • 【java常用接口】Comparator学习

    Comparator 是 Java 中的一个接口,用于定义对象之间的排序规则。它可以用于对集合中的对象进行排序,或者用于自定义排序算法。 对集合中的对象进行排序。 自定义排序算法。 结合 Stream流 实现更便捷的排序操作。 实现 Comparator 接口:创建一个类,实现 Comparator 接口,并重

    2024年01月21日
    浏览(66)
  • Swift学习日记(3) --关于请求多个接口导致UI绘制顺序不正确及GCD

    问题描述:在我写的controller里面 需要去请求三个接口:广告接口 九宫格接口 单曲接口 每个接口对应的是tableview里面每一个cell的数据,为了图省事,我把三个接口直接扔在viewdidload里面,然后在每个接口请求完数据之后刷新一下列表。 代码如下: 这个 fetchDataAndUpdateUI() 是广

    2024年02月03日
    浏览(38)
  • Java比较器(Comparator接口)

    1.当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码,或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,那么可以考虑使用 Comparator 的对象来排序 2.重写compare(Object o1,Object o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回

    2024年02月15日
    浏览(47)
  • java调用接口返回乱码问题

    调用第三方接口。 当调用第三方接口时,存入数据库中的数据正常,打印的数据乱码,在header中加入charset=UTF-8即可。 此处用到了hutool的依赖: 示例代码: 第三方调用接口。 当第三方调用咱们的接口时,可能会出现返回信息中文乱码的情况,我们在自己的方法的注解上加

    2024年02月11日
    浏览(37)
  • Springboot调整接口响应返回时长详解(解决响应超时问题)

    一、前言   当后端对于数据量较大的处理或是某些耗时的操作时,需要先对请求接口的请求进行响应。实际场景中会遇到 请求业务处理流程耗时较长 ,比如长查询,远程调用等,主线程会被一直占用会影响其他请求的响应,导致服务端性能下降。同时, 前端向服务端发送

    2024年01月15日
    浏览(41)
  • 【若依】关于对象查询list返回,进行业务处理以后的分页问题

    1、查询对象Jglkq返回 list,对 list 进行业务处理后返回,但分页出现问题。  2、最终解决方案,改造 TableDataInfo getDataTable(List listVo,List list)方法 返回list中修改: 

    2024年01月25日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包