重写equal方法

转自:https://blog.csdn.net/u012767369/article/details/79362752

1.equals()方法和hashcode()方法两者关系——hashCode方法设计原则

1) 如果两个对象相同(即用equals比较返回true),那么它们的hashCode值一定要相同;

2) 如果两个对象不同(即用equals比较返回false),那么它们的hashCode值可能相同也可能不同;

3) 如果两个对象的hashCode相同(存在哈希冲突),那么它们可能相同也可能不同(即equals比较可能是false也可能是true) 

4) 如果两个对象的hashCode不同,那么他们肯定不同(即用equals比较返回false)

hashCode() 返回散列值,而 equals() 是用来判断两个对象是否等价。等价的两个对象散列值一定相同,但是散列值相同的两个对象不一定等价。

2.重写equals()方法——伪代码

1)自反性:A.equals(A)要返回true

2)对称性:如果A.equals(B)返回true,那么B.equals(A)也要返回true

3)传递性:如果A.equals(B)返回true,B.equals(C)为true, 则A.equals(C)也要为true. 说白了就是 A = B , B = C , 那么A = C.

4)一致性:只要A,B对象的状态没有改变,A.equals(B)必须始终返回true.

5)A.equals(null) 要返回false.

在覆盖 equals() 方法时应当总是覆盖 hashCode() 方法,保证等价的两个对象散列值也相等。

3.重写equals()方法——具体步骤分为两步,先重写equals()方法,后重写hashCode()方法

重写equals()方法

示例类

class Coder{

private String name;

private int age;

}

 

因为默认的equals()实际是判断两个引用是否指向内在中的同一个对象,相当于==,具体遵循以下三个步骤

1)判断是否等于自身

if(otherr == this)

return true;

2)使用instanceof运算符判断other是否为Coder类型的对象

if(!(other instanceof Coder))

return false;

3)比较Coder类中你自定义的数据域,name和age,一个都不能少

Coder o = (Coder)other;

return o.name.equals(name) && o.age == age;

 

注意:第3步中有一个强制转换,如果有人将一个Integer类的对象传到了这个equals中,那么会不会扔ClassCastException呢?这个担心其实是多余的.因为我们在第二步中已经进行了instanceof 的判断,如果other是非Coder对象,甚至other是个null, 那么在这一步中都会直接返回false, 从而后面的代码得不到执行的机会,上面的三步也是<Effective Java>中推荐的步骤,基本可保证万无一失

 

重写hashcode()方法

重写了equals()方法一定要重新hashcode方法,重写时要注意保证Coder对象的所有成员都能在hashCode中得到体现(关键)

@Override

public int hashCode(){

int result = 17;

result = result * 31 + name.hashCode();

result = result * 31 + age;

return result;

}

 

PS:String中hashCode()的实现是 s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

可以看出是对每个字符的ASCII码计算n-1次方后再进行求和,可以最大程度上避免2个不同的String会出现相同的hashCode的情况,至于为什么选择31,感兴趣可以看看这个:https://www.cnblogs.com/nullllun/p/8350178.html

 

4.重写equals()方法而不重写hashCode()方法的风险

Java中通过hashCode()方法来确定一个对象应该位于哪个bucket中,然后在相应的链表中进行查找,在理想的情况下,如果你的hashCode()方法足够健壮,那么每个bucket将会只有一个节点,这样实现了查询操作的常量级别的时间复杂度。一旦你重写了equals()方法,但是没有重写hashCode()方法,那么equals返回为true的对象会因为hashCode不同而放在不同的bucket中,而理论上应该是放在一个bucket中的,同时在进行查询的时候,也会因为定位到不同的位桶而找不到指定的元素(equals为true的目标对象)。因此,重写hashCode的原因是,在A.equals(B)返回true的情况下,A,B的hashCode()要返回相同的值。

 

PS:hashCode()是为哈希表服务的,用于快速定位元素在数组中的位置,不能让hashCode()方法每次都返回一个固定的数,这样的话hashMap和hashSet就失去了意义,哈希表就退化成了链表,每次查询都只是遍历链表,完全失去了hash的作用

 

copy from:https://blog.csdn.net/u012767369/article/details/79362752

_________________________________________________

public boolean equals(Object anObject) {  
   if (this == anObject) {  
       return true;  
   }  
   if (anObject instanceof String) {  
       String anotherString = (String)anObject;  
       int n = count;  
       if (n == anotherString.count) {  
           char v1[] = value;  
           char v2[] = anotherString.value;  
           int i = offset;  
           int j = anotherString.offset;  
           while (n– != 0) {  
               if (v1[i++] != v2[j++])  
                   return false;  
           }  
           return true;  
       }  
   }  
   return false;  
}  

很明显,这是进行的内容比较,而已经不再是地址的比较。依次类推Math、Integer、Double等这些类都是重写了equals()方法的,从而进行的是内容的比较。当然,基本类型是进行值的比较。

它的性质有:

  • 自反性(reflexive)。对于任意不为null的引用值x,x.equals(x)一定是true
  • 对称性(symmetric)。对于任意不为null的引用值xy,当且仅当x.equals(y)true时,y.equals(x)也是true
  • 传递性(transitive)。对于任意不为null的引用值xyz,如果x.equals(y)true,同时y.equals(z)true,那么x.equals(z)一定是true
  • 一致性(consistent)。对于任意不为null的引用值xy,如果用于equals比较的对象信息没有被修改的话,多次调用时x.equals(y)要么一致地返回true要么一致地返回false
  • 对于任意不为null的引用值xx.equals(null)返回false

对于Object类来说,equals()方法在对象上实现的是差别可能性最大的等价关系,即,对于任意非null的引用值xy,当且仅当xy引用的是同一个对象,该方法才会返回true

需要注意的是当equals()方法被override时,hashCode()也要被override。按照一般hashCode()方法的实现来说,相等的对象,它们的hash code一定相等。

hashcode() 方法详解

hashCode()方法给对象返回一个hash code值。这个方法被用于hash tables,例如HashMap。

它的性质是:

  • 在一个Java应用的执行期间,如果一个对象提供给equals做比较的信息没有被修改的话,该对象多次调用hashCode()方法,该方法必须始终如一返回同一个integer。
  • 如果两个对象根据equals(Object)方法是相等的,那么调用二者各自的hashCode()方法必须产生同一个integer结果。
  • 并不要求根据equals(java.lang.Object)方法不相等的两个对象,调用二者各自的hashCode()方法必须产生不同的integer结果。然而,程序员应该意识到对于不同的对象产生不同的integer结果,有可能会提高hash table的性能。

 

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值