平时我们在对集合或数组排序时,会碰到Comparable和Comparator这两个很类似的接口,它们以不同的方式实现了元素的排序功能,今天我们就来谈谈这两个接口的区别,并介绍下Java排序一些常见方法的使用。
首先介绍一下Comparable与Comparator的区别。
Comparable是排序接口,若一个类实现了Comparable接口,该类的对象就支持排序;
而Comparator是比较器接口,我们可以实现一个Comparator接口(一般采用匿名内部类的写法),定义一种对A类的排序规则,而不需要对A类做任何改变。
所以,Comparable相当于内部比较器,而Comparator相当于外部比较器。
下面列出集合排序时一些常用的方法:
- list.sort(comparator)
- Collections.sort(list)
- Collections.sort(list, comparator)
- list.stream().sorted();
- list.stream().sorted(comparator)
可以发现有的排序方法要求提供Comparator接口作为参数,有些则没有要求;
若提供了Comparator接口,则集合的元素无需实现Comparable接口,若元素没有实现Comparable接口,则需要提供Comparator接口。
Comparable接口使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| public class ComparableTest { public static void main(String[] args) { List<Student> list = Arrays.asList( new Student("张三",80), new Student("李四",67), new Student("王五",93) ); Collections.sort(list); System.out.println(list); } }
class Student implements Comparable<Student> { private String name; private int score;
@Override public int compareTo(Student o) { if (this.score > o.score) { return 1; } else if (this.score < o.score) { return -1; } else { return 0; } }
public Student(String name, int score) { this.name = name; this.score = score; }
@Override public String toString() { return "Student{" + "name='" + name + '\'' + ", score=" + score + '}'; } };
|
Comparator接口使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| public class ComparatorTest { public static void main(String[] args) { List<Teacher> list = Arrays.asList( new Teacher("老王", 30), new Teacher("老张", 27), new Teacher("老李", 45) );
list.sort(new Comparator<Teacher>() { @Override public int compare(Teacher o1, Teacher o2) { int age1 = o1.getAge(); int age2 = o2.getAge(); if (age1 > age2) { return 1; } else if (age1 < age2) { return -1; } else { return 0; } } }); System.out.println(list); } }
class Teacher { private String name; private int age;
public Teacher(String name, int age) { this.name = name; this.age = age; }
@Override public String toString() { return "Teacher{" + "name='" + name + '\'' + ", age=" + age + '}'; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; } } ````
可以发现,上面两个例子排序的结果都是从小到大,这种排序顺序在Java里叫做自然排序,采取上面的写法就可以了,如果你想要排序的结果是从大到小,只需要交换大于时和小于时的返回值即可。<br>
这时候,你可能就明白了String、Integer等对象为什么能够排序了,打开Integer类的源码,果然Integer类也实现了Comparable接口。<br> Java中,String、Integer、Double等类,都实现了Comparable接口,而且排序时候的顺序都是自然排序,即从小到大。
### 按字母排序字符串列表的示例
```java List<String> cities = Arrays.asList("c", "a", "B"); cities.sort(Comparator.naturalOrder()); System.out.println(cities);
cities.sort(String.CASE_INSENSITIVE_ORDER); System.out.println(cities);
cities.sort(Comparator.reverseOrder()); System.out.println(cities);
|
Comparator的一些其他技巧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| List<Teacher> list = Arrays.asList( new Teacher("a_t", 30), new Teacher("b_t", 27), new Teacher("c_t", 45), new Teacher("d_t", 30) );
list.sort(Comparator.comparing(Teacher::getAge)); System.out.println(list);
list.sort(Comparator.comparing(Teacher::getAge).reversed()); System.out.println(list);
list.sort(Comparator.comparing(Teacher::getAge).reversed().thenComparing(Teacher::getName).reversed()); System.out.println(list);
|
注意,Teacher类并没有实现Comparable接口。
上面的一些写法用到了lambda表达式,这样可以让我们的代码更加简洁,还没使用的小伙伴快加入吧!
(完)