为什么equals()方法要重写?
判断两个对象在逻辑上是否相等,如根据类的成员变量来判断两个类的实例是否相等,而继承Object中的equals方法只能判断两个引用变量是否是同一个对象。这样我们往往需要重写equals()方法。
我们向一个没有重复对象的集合中添加元素时,集合中存放的往往是对象,我们需要先判断集合中是否存在已知对象,这样就必须重写equals方法。
覆盖equals方法需要遵守的规定
- 1、自反性:对于任何非空引用x,x.equals(x)应该返回true。
- 2、对称性:对于任何引用x和y,如果x.equals(y)返回true,那么y.equals(x)也应该返回true。
- 3、传递性:对于任何引用x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)也应该返回true。
- 4、一致性:如果x和y引用的对象没有发生变化,那么反复调用x.equals(y)应该返回同样的结果。
- 5、非空性:对于任意非空引用x,x.equals(null)应该返回false。
demo
public class Person {
private String name;
public Person(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Person) {
Person person= (Person) obj;
return name.equalsIgnoreCase(person.getName().trim());
}
return false;
}
/*其他代码相同,不再赘述*/
@Override
public int hashCode(){
return new HashCodeBuilder().append(name).toHashCode();
}
public static void main(String[] args){
Person p1=new Person("张三");
Person p2=new Person("张三 ");
List<person> list = new ArrayList<person>();
list.add(p1);
list.add(p2);
System.out.println("是否包含张三:"+list.contains(p1));
System.out.println("是否包含张三:"+list.contains(p2));
}
}
重新equals,必须重新hashcode
代码中的Person类与上一个相同,equals方法完美无缺。在这段代码中,我们在声明时直接调用方法赋值,这其实也是一个内部匿名类的操作。现在的问题是b1和b2这两个boolean值是否都为true?
我们先来看b1,Person类的equals覆写了,不再判断两个地址是否相等,而是根据人员的姓名来判断两个对象是否相等,所以不管我们的new Person(“张三”)产生了多少个对象,它们都是相等的。把“张三”对象放入list中,再检查list中是否包含,那结果肯定是true了。
接着来看b2,我们把张三这个对象作为了Map的键(Key),放进去的对象时张三,检查的对象还是张三,那应该和List的结果相同了,但是很遗憾,结果是false。原因何在呢?
原因就是HashMap的底层处理机制是以数组的方式保存map条目(Map Entry)的,这其中的关键是这个数组下标的处理机制:依据传入元素的hashCode方法的返回值决定其数组的下标,如果该数组位置上已经有了map条目,且与传入的键值相等则不处理,若不相等则覆盖;如果数组位置没有条目,则插入,并加入到map条目的链表中。同理检查键是否存在也是根据哈希码确定文职,然后遍历查找键值的。
那么对象元素的hashCode方法返回的是什么值呢?它是一个对象的哈希码,是由Object类的本地方法生成的,确保每个对象有一个哈希码(这也是哈希算法的基本要求:任意输入k,通过一定算法f(k),将其转换为非可逆的输出,对于两个输入k1和k2,要求若k1=k2,则必须f(k1)= f(k2),但不允许k1≠k2,f(k1)=f(k2)的情况存在)。
回到我们的例子上,由于我们没有重写hashcode方法,两个张三对象的hashcode方法返回值(也就是哈希码)肯定是不相同的,在HashMap的数组中也就找不到对应的Map条目了,于是就返回了false。
equls 与 hashcode的关系
equals 相等,hashcode一定相同
hashcode相等,equals 不一定相等。