一、前言

最近在做一个需求用到了集合的排序,但是这个项目就有点老,用的jdk1.6的,所以不能用Stream流,我就想着把这几种都总结一遍吧,回顾一下。
先说明一下,我们是先对id进行排序,然后再对age进行排序的。

二、方式

(1)Comparator

Person p1 = new Person(100,108,"赵晓东");
        Person p2 = new Person(5,20,"赵晓北");
        Person p3 = new Person(9,88,"赵晓南");
        Person p4 = new Person(10,100,"赵晓西");
        Person p5 = new Person(15,200,"赵晓天");
        ArrayList<Person>  personList = new ArrayList<Person>();
        personList.add(p1);
        personList.add(p2);
        personList.add(p3);
        personList.add(p4);
        personList.add(p5);
        Collections.sort(personList, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                int c = 0;
                //首先按照Id进行排序
                c =o1.getId()-o2.getId();
                if (c==0){
                    //按照age排序
                    c = o1.getAge()-o2.getAge();
                }
                return c;
            }
        });

        personList.stream().forEach(e-> System.out.println(e));

        System.out.println("====================================================");

展示
```java
Person(id=5, age=20, name=赵晓北)
Person(id=9, age=88, name=赵晓南)
Person(id=10, age=100, name=赵晓西)
Person(id=15, age=200, name=赵晓天)
Person(id=100, age=108, name=赵晓东)
====================================================

(2)Comparable

@Data
@AllArgsConstructor
public class Person implements Comparable<Person>{
    private Integer id;
    private Integer age;
    private String name;

    @Override
    public int compareTo(Person o) {
        int c = 0;
        c=this.id-o.id;
        if (c==0){
            c=this.age-o.age;
        }
        return c;
    }
}

展示

Person(id=5, age=20, name=赵晓北)
Person(id=9, age=88, name=赵晓南)
Person(id=10, age=100, name=赵晓西)
Person(id=15, age=200, name=赵晓天)
Person(id=100, age=108, name=赵晓东)

(3)Stream

List<Person> personList1 = personList.stream().sorted(Comparator.comparing(Person::getId).thenComparing(Person::getAge)).collect(Collectors.toList());
        personList1.stream().forEach(e-> System.out.println(e));
Person(id=5, age=20, name=赵晓北)
Person(id=9, age=88, name=赵晓南)
Person(id=10, age=100, name=赵晓西)
Person(id=15, age=200, name=赵晓天)
Person(id=100, age=108, name=赵晓东)

三、性能对比

Comparator

执行时长: 0 毫秒.

Comparable

执行时长: 0 毫秒.

Stream

StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        List<Person> personList1 = personList.stream().sorted(Comparator.comparing(Person::getId).thenComparing(Person::getAge)).collect(Collectors.toList());
        stopWatch.stop();
        System.out.printf("执行时长: %d 毫秒.%n",stopWatch.getTotalTimeMillis());

执行时长: 61 毫秒.

四、原理

comparable

是一个内比较器,实现了这一个排序接口,可以重写comPareTo方法,compareTo方法的返回值是int,有三种情况:
1、比较者大于被比较者,那么返回正整数
2、比较者等于被比较者,那么返回0
3、比较者小于被比较着,那么返回负整数
同时是可以支持和自己比较的。

Comparator

可以认为是一个外比较器。我们若需要控制某个类的次序,可以简历一个"该类的比较器"来进行排序。
所以如果当我们遇到不想按照原先的类进行排序的时候,可以写一个外部的comparator。

Stream

stream和Collection操作不同,有两个基本的特征
Pipelining: 中间操作队徽返回流对象本身。这样多个操作可以串联成一个管道。
内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。Stream提供了内部迭代的方式, 通过访问者模式 (Visitor)实现。

五、总结

从用法方面看,Stream更好,但是有的时候项目不是Jdk1.8的就不得不用其它方式了,
comparable是在java.lang包下面的。comparator是在java.util包下面的,
comparable需要实现compareTo方法,comparator需要实现compare方法。
comparable通常需要在类里面写,而comparator不需要设置实体类里面。
从性能上面看,coomparable、comprartor、Stream性能相差不大,但是Stream会更加便利。