目录
2.1.Object.equals(基于Object类的equals方法的比较)
2.2.Comparable.compareTo(基于Comparable接口的compareTo方法的比较)
2.3.Comparator.compare(基于比较器的比较-基于Comparator接口实现的compare方法)
1.基本类型的比较
在Java中,基本类型的对象可以直接比较大小。
public class TestCompare {
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println(a > b);
System.out.println(a < b);
System.out.println(a == b);
char c1 = 'A';
char c2 = 'B';
System.out.println(c1 > c2);
System.out.println(c1 < c2);
System.out.println(c1 == c2);
boolean b1 = true;
boolean b2 = false;
System.out.println(b1 == b2);
System.out.println(b1 != b2);
}
}

2.对象的比较
class Card{
public int rank; //数值
public String suit; //花色
public Card(int rank, String suit) {
this.rank = rank;
this.suit = suit;
}
}
public class TestPriorityQueue {
public static void main(String[] args) {
Card c1 = new Card(1, "♣");
Card c2 = new Card(2, "♣");
Card c3 = c1;
//c1, c2, c3分别是Card类型的引用变量
// System.out.println(c1 > c2); //编译报错
System.out.println(c1 == c2); //编译成功,打印false,因为c1和c2指向不同对象
// System.out.println(c1 < c2); //编译报错
System.out.println(c1 == c3); //编译成功,打印true,因为c1和c3指向同一对象
}
}

可知:
- Java中引用类型的变量不能直接按照">"或者"<"方式进行比较,而"=="可以比较。
- 因为对于用户实现自定义类型,都默认继承自Object类,而Object类中提供了equals方法。"=="默认调用equals方法。
- equals方法的比较规则是:没有比较引用变量引用对象的内容,而是直接比较引用变量的地址。
2.1.Object.equals(基于Object类的equals方法的比较)
比较2个自定义的对象是否相等,默认比较2个对象的地址是否相等,覆写Object基类提供的equals方法。
- this == o
- o == null
- !(o instanceof Student)
- this.name.equals(stu.name) 按照类的实现目标完成比较
- 下调用其他引用类型的比较,也要用equals
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override //检查是否覆写正确,没报错,说明写对了
public boolean equals(Object o) {
//this表示当前对象,我自己和传进来的是一个东西,自己和自己比,为true
if(this == o) {
return true;
}
if(o == null || !(o instanceof Student)) {
//传入对象为空 或 不是Student类型对象(o不是披着Student外衣的Object)
return false;
}
//此时o一定不是空,且是Student对象,脱掉o的小马甲
//向下转型,还原回来
Student stu = (Student) o;
return this.name.equals(stu.name);
}
public static void main(String[] args) {
Student stu1 = new Student("张三", 18);
Student stu2 = new Student("李四", 20);
Student stu3 = new Student("张三", 30);
System.out.println(stu1.equals(stu2)); //false
System.out.println(stu1.equals(stu3)); //true
}
}

缺点:equals方法只能按照相等进行比较,不能按照大于,小于的方式进行比较。
2.2.Comparable.compareTo(基于Comparable接口的compareTo方法的比较)
- 对用户自定义类型,如果想要按照大小方式进行比较,在定义类时,实现Comparable接口即可,然后重写类中的compareTo方法。
- Comparable是JDK提供的泛型的比较接口类,是java.lang中的接口,可直接使用。
- 当一个类覆写了Comparable接口(规范/能力),就表示该类具备了可比较的能力,就不需要equals方法。
- 源码实现如下:

import java.util.Arrays;
public class Student2 implements Comparable<Student2> {
private String name;
private int age;
public Student2 (String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student2{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Student2 o) {
if(this.age == o.age) {
return 0;
} else if(this.age < o.age) {
return -1;
} else {
return 1;
}
}
public static void main(String[] args) {
Student2 stu1 = new Student2("张三", 18);
Student2 stu3 = new Student2("张三", 30);
Student2 stu2 = new Student2("李四", 20);
System.out.println(stu1.compareTo(stu2)); //-1
System.out.println(stu1.compareTo(stu3)); //-1
Student2[] student2s = {stu1, stu3, stu2};
Arrays.sort(student2s);
System.out.println(Arrays.toString(student2s));
}
}

2.3.Comparator.compare(基于比较器的比较-基于Comparator接口实现的compare方法)
- Comparator是java.util包中的泛型接口类,使用时必须导入对应的包。
- 有了这个接口后,需要怎么排序就创建一个新的实现了Comparator接口的子类即可,对原类无影响。
- Comparator比Comparable接口灵活。例:假设之前是按照年龄升序排序,现在需要按照年龄降序排序:
- Comparable接口:得修改Student类的实现,修改CompareTo方法。原则上Comparable只能实现一种大小关系比较(绑定在Student中)
- Comparator比较器:可以不修改任何Student类的代码,实现不同的比较关系。Comparator可以实现无数种的比较(23种模式之一的策略模式)
- 二者最大的用处在于排序,HashMap和HashSet要求自定义的类必须覆写equals或实现比较接口。
- 用户自定义的比较器类,实现Comparator接口。源码实现如下:
public interface Comparator<T> {
//返回值
// <0 表示o1指向的对象小于o2指向的对象
// >0 表示o1指向的对象大于o2指向的对象
// ==0 表示o1指向的对象等于o2指向的对象
int compare(T o1, T o2);
//...
}
import java.util.Arrays;
import java.util.Comparator;
public class Student3 {
private String name;
private int age;
public int getAge() {
return age;
}
public Student3 (String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student3{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//Student这个类还不具备可比较的能力,创建了一个新的类,就是比较Student对象大小关系
//相当于把比较Student对象大小关系这个事外包了,Student类自己不干这些事
/**
* 升序
*/
static class AgeSec implements Comparator<Student3> {
@Override
public int compare(Student3 o1, Student3 o2) {
if(o1.getAge() == o2.getAge()) {
return 0;
} else if(o1.getAge() > o2.getAge()) {
return 1;
}
return -1;
}
}
//要将Student年龄按照降序排序,再创建一个比较器,不修改Student类的内容,称为无侵入编程
/**
* 降序
*/
static class AgeDeSec implements Comparator<Student3> {
@Override
public int compare(Student3 o1, Student3 o2) {
if(o1.getAge() == o2.getAge()) {
return 0;
} else if(o1.getAge() > o2.getAge()) {
return -1;
}
return 1;
}
}
public static void main(String[] args) {
Student3 stu1 = new Student3("张三", 18);
Student3 stu3 = new Student3("张三", 30);
Student3 stu2 = new Student3("李四", 20);
Student3[] student3s = {stu1, stu3, stu2};
AgeSec ageSec = new AgeSec();
Arrays.sort(student3s, ageSec);
System.out.println(Arrays.toString(student3s)); //升序打印
AgeDeSec ageDeSec = new AgeDeSec();
Arrays.sort(student3s, ageDeSec);
System.out.println(Arrays.toString(student3s)); //降序打印
}
}

PS:
- ctrl + Y 可将误删的所有内容一次性还原
- ctrl + Z 撤销,可将误删的内容的最后一步还原
3.总结
| 覆写的方法 | 说明 | 位置,比较内容 |
| Object.equals | Object类提供的equals方法,因为所有类都是继承自Object的,所以直接覆写即可。默认比较2个对象的地址是否相等,只能比较是否相等,不能比较大小关系。 | 类内 比= |
| Comparable.compareTo | java.lang中的接口,需要手动实现接口,侵入性较强,但一旦实现,每次用该类都有顺序,属于内部顺序。 | 类内 比=、>、< |
| Comparator.compare | java.util中的接口,需要实现一个比较器对象,对待比较类的侵入性弱,但对算法代码实现侵入性强。 | 类外 比=、>、< |
文章详细介绍了Java中基本类型和对象的比较方式,包括Object的equals方法用于对象的相等性比较,Comparable接口的compareTo方法实现对象的自然排序,以及Comparator接口的compare方法用于自定义排序。此外,还讨论了Comparable与Comparator接口的区别和应用场景。
128





