java 中排序写法的几种方式

java 中排序写法的几种方式

对于数组:

假如说我们有这么一个Person对象数组,我们需要对其排序,会怎么样排呢?

       Person[] peoples = new Person[4];
       peoples[0] = new Person("zhangsan", 11);
       peoples[1] = new Person("lisi", 9);
       peoples[2] = new Person("wangwn", 55);
       peoples[3] = new Person("zhaoliu", 44);

想想正常的生活场景,我们对人进行排序,当然是需要有一个度量标准的,有的是按照人的升高在排序,有的是按照名字的长短排序,有的是按照在公司的业绩排序,所依排序需要有一个度量标准。
在jdk中有一个工具类,我们直接开撸,假如说我们是对年龄进行排序的

        Arrays.sort(peoples, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge()-o2.getAge();
            }
        });

Comparator是一个函数式接口的中立的排序器,会将要排序的两个对象穿入其中的抽象方法compare(o1,o2),如果o1.getAge()-o2.getAge()>0 那么就是升序否则就是降序,

刚才说过,Comparator<> 是一个函数式接口,那么我们就可以用函数式的方式来简化这个匿名类,格式如下

 Arrays.sort(peoples, (Person o1, Person o2) -> o1.getAge()-o2.getAge());

但是我们看到上面的两个参数都对应了Person类型,感觉很啰嗦,还好java8 中的函数式编程在依赖于泛型的情况下,是能够做出相应的类型推到的,所以我们又可以简写成下面这个格式

 Arrays.sort(peoples, (o1, o2) -> o1.getAge()-o2.getAge());

java8 中还有一个特性,就是借口中也能够有非抽象方法,comparingInt,返回的就是Comparator实例,穿入的参数是一个ToIntFunction,这个toIntFunction要求传入一个T 类型,返回一个int类型刚好符合我们这里的要求,
当然ToIntFunction可以用java8 中的另一个新特性,叫做行为参数化,格式如下


 Arrays.sort(peoples, Comparator.comparingInt(Person::getAge));

运行上面的运行结果如下

Person{name=‘lisi’, age=9}
Person{name=‘zhangsan’, age=11}
Person{name=‘zhaoliu’, age=44}
Person{name=‘wangwn’, age=55}

那么结果没错就是我们想要的老铁

那么如果我们这里的Comparator没有,或者就穿入的为空,我们点到源码中去看

我们看到Arrays.sort()有一个一个参数的重载方法,我们可以直接用这个方法跑一下,最后报错,报错如下

Exception in thread "main" java.lang.ClassCastException: com.louis.javasource.Person cannot be cast to java.lang.Comparable

既然报错了,我们就点进去看看为什么会报这个错,我们会发现Arrays.sort(Object o)
会调用了一个叫binarySort的方法,其中有这么一段,就是将数组对象转化为Comparable,如下


            Comparable pivot = (Comparable) a[start];

            int left = lo;
            int right = start;
            assert left <= right;

但是你知道我们的Person对象是没有实现这样的一个接口,那么如果我们调用Arrays.sort(peoples)这个方法肯定会报错,而且我们从名字上面看,也应该知道
JDK给我们提供的排序方式默认是BinarySort 也就是二分排序,
所以如果我们想要调用单参数的sort方法,那么我们就需要让Person 实现 Comparable 这个接口,那么这个接口和Comparator有什么区别呢?

对比他们的名字,大概也能知道一二,

  1. Comparable 是代表着一种能力,那么实现这种接口就拥有了这种能力,但是需要自己提前实现Comparable的抽象方法,在具体使用的时候,逻辑就不能随便改了
  2. Comparator是比较器,需要用什么对象的什么属性去比较,在调用比较器的时候,实现其接口就可以了,
    在我们真是项目的时候,有时候在设计的时候是没有对某个对象设计成可排序的,但是我们后期真的是需要对其排序的,那么我们就可以用Comparator这种方式进行操作了

对于集合

我们可以直接调用集合的sort方法,但是我们发现sort方法是有一个参数就是Comparator,我们可以点进源码看看,发现原来也是调用Array.sort(Comparator),那就超级简单了,所有逻辑和上面一样就可以,如果我们传入了Comparator,就以我们穿入的方式进行排序,如果没有传入Comparator,那么我们就必须实现一个Comparable

        List<Person> people = new ArrayList<>();

        people.add(new Person("zhangsan", 11));
        people.add( new Person("lisi", 9));
        people.add(new Person("wangwn", 55));
        people.add(new Person("zhaoliu", 44));
        
        people.sort(null);

java 8中,Stream还提供了流式排序的方法,其实整体的思路和上面提到的方式是一模一样,但是需要注意的是,如果使用Stream中的sorted来排序,最后是会产生一个流,我们需要使用终止操作,让流转化成一个新的集合,使用的形式如下,可以将新的collect和原来的people最后的结果打印出来做一个对比,但是需要一提的是,这里sorted(Comaprator c)这个方法是不能穿null的,写法如下

List<Person> collect = people.stream().sorted(null).collect(Collectors.toList());//这种写法是会报空指针异常的
List<Person> collect = people.stream().sorted().collect(Collectors.toList());

那么现在关于数据排序的方式总结就是上面这些了,如有写的不好的地方,欢迎大家留言指正

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值