在Java中,基本类型的对象可以直接比较,而自定义类型,默认是用equal方法,但是它没有比较引用变量引用对象的内容,而是直接比较引用变量的地址,本文记录了解决该问题的几种方法。
基本数据类型,一般可以使用==直接比较,字符串String类型可以使用equal进行比较。
作用:
(1)用于基本数据类型的比较;
(2)判断引用是否指向堆内存的同一块地址。
作用:
用于引用类型,在默认情况下,比较引用类型的内存地址是否相等;也可以根据需求,重写equals方法。
Object类equals()方法源码:
对于引用类型,==会直接比较引用的地址,而用equals则比较的是引用的内容。
缺点:equals只能按照相等进行比较,不能按照大于、小于的方式进行比较。
如下重写equals方法,只能对年龄或者名字按照相等的方式比较。
代码如下(示例):
import java.util.Objects;
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 || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
public class Demo {
public static void main(String[] args) {
Student s1 = new Student("王一", 20);
Student s2 = new Student("金木", 19);
System.out.println(s1.equals(s2));
}
}
Comparable是jdk提供的泛型的比较接口类,源码实现具体如下:
public interface Comparable<T> {
public int compareTo(T o);
}
Comparable是java.lang中的接口类,可以直接使用。
如下,自定义Student类,通过实现Comparable接口并重写compareTo方法,通过年龄对Student类的大小进行比较。
import java.util.Objects;
class Student implements Comparable<Student> {
public String name;
public int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Student o) {
if (o == null) return 1;
return this.age - o.age;
}
}
public class ComparatorDemo {
public static void main(String[] args) {
Student s3 = new Student("小王", 19);
Student s4 = new Student("小刘", 22);
System.out.println(s3.compareTo(s4)); //小于0 表示s3.age < s4.age
}
}
步骤:
(1)用户自定义比较器类,实现Comparator接口;
(2)覆写Comparator中的compare方法。
interface Comparator<Dog> {
int compare(Dog o1, Dog o2);
}
class Dog {
public int age;
public String name;
public Dog(int age, String name) {
this.age = age;
this.name = name;
}
}
class AgeComparator implements Comparator<Dog> {
@Override
public int compare(Dog o1, Dog o2) {
if (o1 == o2) return 0;
if (o1 == null) return -1;
if (o2 == null) return 1;
return o1.age - o2.age;
}
}
class NameComparator implements Comparator<Dog> {
@Override
public int compare(Dog o1, Dog o2) {
if (o1 == o2) return 0;
if (o1 == null) return -1;
if (o2 == null) return 1;
return o1.name.compareTo(o2.name);
}
}
public class ComparatorDemo {
public static void main(String[] args) {
Dog dog1 = new Dog(3, "aba");
Dog dog2 = new Dog(2, "aaa");
Dog dog3 = new Dog(3, "acd");
//年龄比较器
AgeComparator ageComparator = new AgeComparator();
//名字比较器
NameComparator nameComparator = new NameComparator();
System.out.println(ageComparator.compare(dog1,dog2)); //>0,表示dog1.age > dog2.age
System.out.println(nameComparator.compare(dog1, dog3)); //
}
}
覆写的方法 | 说明 |
---|---|
Object.equals | 由于所有类都继承自Object,所以直接覆写即可,但只能比较相等与否 |
Comparable.compareTo | 需要手动实现接口,侵入性较强,一旦实现,每次用该类都有顺序,属于内部顺序 |
Comparator.compare | 需要实现一个比较器对象,对待比较类的侵入性弱,但对算法代码实现侵入性强 |