1 Object.equals
==和equals:
- p==q表示的是p和q两个引用指向同一个对象。
- p.equals(q)表示p和q指向的对象值是否相等。
1 覆写equals()方法来实现对象间的比较(是否相等)
Card类覆写equals方法实现牌类对象的比较:
public class Card {
public int rank; // 数值
public String suit; // 花色
public Card(int rank, String suit) {
this.rank = rank;
this.suit = suit;
}
@Override
public boolean equals(Object obj) {
if(this == obj) {
return true;
}
if(!(obj instanceof Card)) {
return false;
}
Card card = (Card) obj;
return rank == card.rank && suit.equals(card.suit);
}
public static void main(String[] args) {
Card card1 = new Card(1,"♠");
Card card2 = new Card(1,"♠");
System.out.println(card1 == card2); //false
System.out.println(card1.equals(card2)); //true
}
}
equals覆写套路:
1)若指向同一个对象则返回true
2)如果传入的对象类型不是Card,则返回false.
3)在Card中只要花色suit和数值rank一样就认为是相等的。
2 Comparable
Comparable接口:
public interface Comparable<E> {
// 返回值:
// < 0: 表示this 指向的对象小于o 指向的对象
// == 0: 表示this 指向的对象等于o 指向的对象
// > 0: 表示this 指向的对象等于o 指向的对象
int compareTo(E o);
}
对于大小排序,通过实现Comparable并覆写compareTo来实现对象之间的比较,不过每次只能传入一个比较属性。
class Person implements Comparable<Person>{
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Person o) {
//return this.age - o.age;
//按姓名排序了,如果再想按年龄排序,那么需要重新更改程序
return this.name.compareTo(o.name);//按姓名排序
}
}
public static void main(String[] args) {
Person[] people = new Person[3];
people[0] = new Person("wangfei",87);
people[1] = new Person("zhangfei",19);
people[2] = new Person("angbai",38);
Arrays.sort(people);
System.out.println(Arrays.toString(people));
}
3 比较器—Comparator
通过实现多个比较器,可以实现对年龄,姓名等进行排序,而无需再反复修改compareTo方法。
通过比较器实现年龄,姓名比较:
class Person {
public String name;
public int age;
public Person1(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person1{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
//比较器ComparatorByAge,用来比较年龄
class ComparatorByAge implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
if (o1 == o2) {
return 0;
}
if (o1 == null) {
//o1.age - o2.age,o1 == null,返回-1,说明o1<o2
return -1;
}
if (o2 == null) {
//o1.age - o2.age,o2 == null,返回1,说明o1>o2
return 1;
}
return o1.age - o2.age;
}
}
//比较器ComparatorByName,用来比较姓名
class ComparatorByName implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
if (o1 == o2) {
return 0;
}
if (o1 == null) {
return -1;
}
if (o2 == null) {
return 1;
}
return o1.name.compareTo(o2.name);
}
}
public static void main(String[] args) {
Person1[] people = new Person[3];
people[0] = new Person("wangfei",87);
people[1] = new Person("zhangfei",19);
people[2] = new Person("angbai",38);
ComparatorByAge comparatorByAge = new ComparatorByAge();
ComparatorByName comparatorByName = new ComparatorByName();
Arrays.sort(people,comparatorByName);//在排序时传入比较器
System.out.println(Arrays.toString(people));
}
覆写的方法说明
1)Object.equals:因为所有类都是继承自Object 的,所以直接覆写即可,不过只能比较相等与否。
2)Comparable.compareTo:需要手动实现接口,侵入性比较强,但一旦实现,每次用该类都有顺序,属于内部顺序。
3)Comparator.compare:需要实现一个比较器对象,对待比较类的侵入性弱,但对算法代码实现侵入性强。
4 和java 集合框架的配合
1) 使用contains 等方法时,内部在调用元素的equals 方法,所以要求元素覆写equals 方法。
2)使用HashMap,key 的比较时,内部会调用equals 方法,所以要求元素覆写equals 方法。
3)使用排序相关方法时,内部需要进行比较,所以可以选择实现Comparable 或者传入一个Comparator。
4) 使用TreeMap,key 需要进行大小比较,所以可以选择实现Comparable 或者传入一个Comparator。
通过覆写equals实现和对象相关的contains方法
class Student {
public String name;
public Student(String name) {
this.name = name;
}
@Override
public boolean equals(Object obj) {
if(obj == this) return true;
if(obj instanceof Student) {
Student student = (Student) obj;
return this.name.equals(student.name);
}
return false;
}
}
public static void main(String[] args) {
List<Student> list = new ArrayList<>();
Student student1 = new Student("gaobo");
Student student2 = new Student("gaobo");
list.add(student1);
System.out.println(list.contains(student2));
}