1. 引入
基本类型可以直接比较大小,但是我们自定义的类类型可能就无法比较,如果自定义类的类型本身有多个属性的话,那么是以什么样的方式去比较这个类型对象的大小呢?
对于上述自定义的类类型的比较大小,我们有以下三种处理方式:
- 覆盖基类的 equals 方法
- 基于 comparable 接口类的比较
- 基于比较器比较
2. 方法一:覆写基类的 equals
2.1 介绍
对于自定义的类型,都默认继承了 object 类,而 object 类中提供了 equals 方法。
故我们可以使用 equals 方法去判断两个对象是不是相等。但是并不是任何情况都适用,下面为 object 类中 equals 方法的定义

我们知道对于引用类型,用 == 号比较的其实是引用变量的地址,所以即使两个对象的值相等,但是由于地址不同所以结果也可能是错的,并且还由于自定义类中的属性不为1,所以不重写基类的 equals 方法的话,是无法正确比较对象的。
2.2 覆写 equals 方法的规则
- 如果指向同一个对象,则返回 true
- 如果传入的值为 null,则返回 false
- 如果传入的对象类型不是自定义类或其子类,则返回 false
- 最后比较对象的各个属性,如果是基本类型,则可以直接用 == 比较;如果是引用类型,则使用 equals 方法比较
2.3 实现代码
以下用自定义的 student 类为例,重写其基类的 equals 方法
class student{
public string name;
public int age;
public student(string name, int age) {
this.name = name;
this.age = age;
}
@override
public boolean equals(object o){
if(this==o){
return true;
}
if(o==null || !(o instanceof student)){
return false;
}
student c=(student)o;
return this.name.equals(c.name) && this.age==c.age;
}
}
2.4 局限性
覆写基类 equals 的方法虽然可以使自定义的类被比较,但是该方法只能进行相等和不相等的比较,不能按照大于或小于的方式进行比较。
3. 方法二:基于 comparable 接口的比较
3.1 介绍
该方法在 解析 java 的多态、抽象类和接口 这章介绍过了,有兴趣了解的 uu 可以去那篇文章里面看看
注意:
comparable 是 java.lang 中的接口类,可以直接使用。
3.2 使用方法
- 先让自定义的类继承 comparable 接口
- 再根据我们要以自定义类的哪个属性去比较,来重写 comparable 类中的 compareto 方法
3.3 实现代码
以下用自定义的 student 类为例,以 name 为我们要比较的属性
class student implements comparable<student>{
publice string name;
public int age;
public student(string name, int age) {
this.name = name;
this.age = age;
}
@override
public int compareto(student o){
return this.name.compareto(o.name);
}
}
3.4 局限性
该方法虽然可以让不同对象根据某一个属性来比较大小,但是当我们确定好了以哪一个属性来比较对象的话,那么当我们想要使用另一个属性比较对象时,则需要修改重写 compareto 方法
4. 方法三:基于 comparator 接口,自定义比较器的比较
4.1 介绍
该方法在 解析 java 的多态、抽象类和接口 这章介绍过了,有兴趣了解的 uu 可以去那篇文章里面看看
注意:
comparator 是 java.util 包中的泛型接口类,使用时必须导入对应的包。
4.2 使用方法
- 我们选择一个自定义类中要比较的属性,可以再定义一个类(即比较器),继承于 comparator 接口
- 在该接口中,重写 comparator 接口的 compare 方法,该方法重写的就是对这个属性比较的规则
- 使用时我们就使用 compare 方法,
4.3 实现代码
以下用自定义的 student 类为例,分别以 age、name 为我们要比较的属性来构造比较器
class student{
public string name;
public int age;
public student(string name, int age) {
this.name = name;
this.age = age;
}
}
// 以 student 类中的 name 属性构造比较器
class namecomparator implements comparator<student> {
@override
public int compare(student o1, student o2){
return o1.name.compareto(o2.name);
}
}
// 以 student 类中的 age 属性构造比较器
class agecomparator implements comparator<student>{
@override
public int compare(student o1, student o2){
return o1.age-o2.age;
}
}
使用比较器来进行比较
public class testdemo{
public static void main(string[] args){
student s1=new student("tom",18);
student s2=new student("alen",25);
// 以 name 的大小来比较
namecomparator namecomparator = new namecomparator();
system.out.println(namecomparator.compare(s1,s2));
// 以 age 的大小来比较
agecomparator agecomparator = new agecomparator();
system.out.println(agecomparator.compare(s1,s2));
}
}
// 结果为:19 和 -7
5. 三种方式对比
| 覆写的方法 | 说明 |
|---|---|
| object.equals | 因为所有类都是继承自 object 的,所以直接覆写即可,但是只能比较相等于不相等,不能比较大于或小于 |
| comparable.compareto | 需要手动实现接口,侵入性较强。一旦实现,每次用该类都有指定的顺序,属于内部顺序。但如果要更换比较的方式,则要修改 comparato 方法 |
| comparator.compare | 需要实现一个比较器,对待比较类的侵入性较弱。每次使用,都要确定比较器 |
6. 总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论