问题导向:最近在项目开发中遇到了比较一个ArrayList<People>对象是否包含某一个people类的实例,我直接调用ArrayList的contains方法结果被老大训了一顿,因为我比较两个对象是都相等其实是比较两个对象的内容是否相同,而不是地址。而直接调用Contains()方法,底层实现其实是调用了Object类的equals()方法,Object类的equals方法底层实使用==比较两个对象地址是否相同,我们要比较类对象的内容是否相同,则需要重写这个类(我这里是People类)的equals方法才可以。
注意:当我们重写某个类的equals方法时候,通常有必要重写该类的hashCode()方法,以满足HashCode方法的常规规定,即对象相等,对象对应的哈希码也应该相等。即:
(1)、若peopleA.equals(peopleB) 为true,则peopleA.hashCode==peopleB.hashCode也应该为true;
(2)、若peopleA.hashCode!=peopleB.hashCode,则peopleA.equals(peopleB)为false
源码解析:
ArrayList的contains方法源码调用了indexOf(Object o)方法
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
indexOf(Object o)方法
首先判断Object对象是否为空,要是为空就返回当前对象为空的那个位,否则直接调用Object对象的equals方法,进行比较两个对象是否相同。
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
Object 的equals方法
该方法比较的是两个对象的内存地址是否相同。
public boolean equals(Object obj) {
return (this == obj);
}
应用实例:重写people类
重写equals方法四个步骤:
(1)使用==判断参数是否是这个对象的引用
(2)使用instanceof判断参数是否是正确的类型
(3)把参数转换成正确的类型
(4)对于参数的各个属性,是都跟对象的属性值是否相等。
import lombok.Data;
@Data
public class People{
private String name;
private String sex;
private String like;
@Override
public int hashCode() {
String uniCode = "name"+"sex"+"like";
return uniCode.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (obj instanceof People) {
People p = (People) obj;
if (p.getName().equals(this.name) && p.getSex().equals(this.sex) && p.getLike().equals(this.like)) {
return true;
}
return false;
}
return false;
}
}