一、概述
Java 提供的 Comparable 和 Comparator 接口都是为我们解决比较两个对象的问题,都能实现数组和集合的排序。
两者也有所区别:
- Comparable 接口位于包 java.lang 下;Comparator 接口位于包 java.util 下。
- Comparable 接口——Java类库中的 Byte、Short、String 以及 BigDecimal 等都实现了 Comparable 接口,可以直接调用,用于比较两个对象大小,十分方便,称为自然排序;Comparator 接口——主要用集合的排序,根据不同需求的排序方式直接接口实现,易于功能扩展,不影响原代码,称为比较器排序。
- 实现 Comparable 接口需要重写 compareTo()方法,而实现 Comparator 接口需要重写 compare()方法,两个方法返回值都是 int 类型,根据返回值来判断比较对象的大小,从而实现排序。
二、Comparable接口——自然排序
1、默认的 compareTo()方法
Comparable 接口中的 compareTo()方法判断这个对象相对于比较对象的顺序,小于返回负整数,等于返回 0,大于返回正整数。
(1) 单个字符的比较——返回参与比较的前后两个字符的 asc 码的差值。
String a1 = "a";
String a2 = "c";
System.out.println(a1.compareTo(a2));//结果为-2
(2)字符串的比较——参与比较的两个字符串如果首字符相同,则比较下一个字符,直到有不同的为止,返回该不同的字符的asc码差值;
String a1 = "aa";
String a2 = "ad";
System.out.println(a1.compareTo(a2));//结果为-3
(3)字符串的比较——如果两个字符串长度不同,可以参与比较的字符又完全一样,则返回两个字符串的长度差值;
String a1 = "aa";
String a2 = "aa12345678";
System.out.println(a1.compareTo(a2));//结果为-8
(4)返回为正数表示 a1>a2,返回为负数表示 a1<a2,,返回为 0 表示 a1==a2;
(5)数字类型不能用 compareTo,int 跟 int 的比较不能用compareTo方法。直接用大于(>) 、小于(<) 、等于(==) 或者不等于(!=)来比较即可。(也可以先把 int 转换成 String 再进行比较)
int num1 = 4;
int num2 = 5;
num1.compareTo(num2);//Cannot invoke compareTo(int) on the primitive type int
2、实现Comparable接口,重写compareTo()
public class Rectangle implements Comparable{
int length;
int width;
public Rectangle(int length, int width) {
this.length = length;
this.width = width;
}
public int getArea(){
return length * width;
}
@Override
public int compareTo(Rectangle o) {// 重写比较方法
if(getArea() > o.getArea()){// 面积比较
return 1;
}else if(getArea() < o.getArea()){
return -1;
}else{
return 0;
}
}
public static void main(String[] args) {
Rectangle rect = new Rectangle(2, 2);
System.out.println(rect.compareTo(new Rectangle(3, 3)));
System.out.println(rect.compareTo(new Rectangle(1, 3)));
System.out.println(rect.compareTo(new Rectangle(2, 2)));
}
}
测试结果:
-1
1
0
3、sort()方法——Arrays.sort()、Collections.sort()
由于 Comparable 对象都有 compareTo 方法,sort 方法就可以使用 compareTo 方法的结果来对数组或者 list 的对象进行比较和排序。测试代码如下:
// 数组,int型
int[] num = {2, 5, 1, 4};
Arrays.sort(num);
for (int i = 0; i < num.length; i++) {
System.out.print(num[i] + " ");
}
System.out.println();
// 数组,String
String[] animal = {"cat", "dog", "chicken", "pig"};
Arrays.sort(animal);//数组排序的类
for (String s : animal) {
System.out.print(s + " ");
}
System.out.println();
// 集合,String
ArrayList strings = new ArrayList<>();
strings.add("chicken");
strings.add("cat");
strings.add("dog");
strings.add("pig");
Collections.sort(strings);//list排序的类
for (String s : strings) {
System.out.print(s + " ");
}
测试结果:
1 2 4 5
cat chicken dog pig
cat chicken dog pig
三、Comparator 接口——比较器排序
Comparator 接口的使用:在外部定义比较器实现 Comparator 接口,重写 compare(T o1,T o2) 方法,该方法返回一个 int 型的结果。若方法中定义(o1 - o2),则返回负数表示 o1 小于 o2,返回 0 表示 o1 和等于o2,返回正数表示 o1 大于 o2。
重写好 compare 方法之后,可调用Collections.sort(list, c)对集合进行排序,其中参数 list 为要要排序的集合,参数 c 为实现了 Comparator 接口的对象(它决定了排序的方式)。
测试代码如下:
// 明星类
class Star{
private String name;
private int age;
public Star(){
super();
}
public Star(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String toString(){
return "[name: " + name + ", age: " + age + "]";
}
}
public class Star_Comparator extends Star implements Comparator{
public Star_Comparator(){
super();
}
public Star_Comparator(String name, int age){
super(name, age);
}
@Override
public int compare(Star_Comparator o1, Star_Comparator o2) {
// 排序时先看姓名,再看年龄;比较年龄时,用o1 - o2,则排序结果为正序(从小到大)
if(o1.getName() == o2.getName()){
return o1.getAge() - o2.getAge();
}else{
return o1.getName().compareTo(o2.getName());
}
}
public static void main(String[] args) {
Star_Comparator s1 = new Star_Comparator("pual", 31);
Star_Comparator s2 = new Star_Comparator("kobe", 24);
Star_Comparator s3 = new Star_Comparator("wade", 34);
Star_Comparator s4 = new Star_Comparator("kobe", 34);
List<Star_Comparator> list = new ArrayList<>();
list.add(s1);
list.add(s2);
list.add(s3);
list.add(s4);
System.out.println(list);
Collections.sort(list, new Star_Comparator());
System.out.println(list);
}
}
测试结果:
[[name: pual, age: 31], [name: kobe, age: 24], [name: wade, age: 34], [name: kobe, age: 34]]
[[name: kobe, age: 24], [name: kobe, age: 34], [name: pual, age: 31], [name: wade, age: 34]]