Java 中hashCode()和equals()方法

Java中,涉及到两个对象的比较时,我们会用到hashCode()和equals()。这两个方法是Object类中定义的方法。


1. api中的描述

(1)hashCode()
hashCode()方法给对象返回一个hash code值。这个方法被用于hash tables,例如HashMap。
它的性质是:

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

大量的实践表明,由Object类定义的hashCode()方法对于不同的对象返回不同的integer。

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

它的性质有:

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

对于Object类来说,equals()方法在对象上实现的是差别可能性最大的等价关系,即,对于任意非null的引用值x和y,当且仅当x和y引用的是同一个对象,该方法才会返回true。
需要注意的是当equals()方法被override时,hashCode()也要被override。按照一般hashCode()方法的实现来说,相等的对象,它们的hash code一定相等。


2. 总结

  1. 在Object类中,未覆盖的hashcode()方法产生的hashcode, 可标识该对象在hash表中位置。

  2. 由于hash表可能会产生hash冲突,所以hashCode相同的对象不一等相等。

  3. 在Object类中,未覆盖的equals方法,使用“==”进行比较的,比较的是两个对象的地址是否相同。

  4. 如果两个对象equals比较为真,即两个对象相等,则两个对象的hashcode一定相同;反过来,两个对象的hashcode相同,不代表两个对象相同(有可能hash冲突),equals比较不一定为真

  5. 在hashset 或者hashMap中,新加入一个对象的时候,它会使用对象的HashCode()值来判断对象加入的位置,但同时也会与其他的已经加入的对象的HashCode作对比,如果没有相符的hashcode,Hahset或者HashMap就会假设新对象没有重复出现。如果HashCode()相同,接下来才会比较两个对象是否真正相同。
    采用这种先比较hashcode才比较是否相等的方式,可以极大地提高hashset,hashmap查找插入的效率。(时间复杂度为O(1))


3.覆盖Object类的hashCode()和equals()方法

我们可以根据自己的需要来覆盖Object类中的hashCode()和equals()方法。
例如String中的hashcode()和equals()方法

 /** 
    * Returns a hash code for this string. The hash code for a 
    * <code>String</code> object is computed as 
    * <blockquote><pre> 
    * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] 
    * </pre></blockquote> 
    * using <code>int</code> arithmetic, where <code>s[i]</code> is the 
    * <i>i</i>th character of the string, <code>n</code> is the length of 
    * the string, and <code>^</code> indicates exponentiation. 
    * (The hash value of the empty string is zero.) 
    * 
    * @return  a hash code value for this object. 
    */  
   public int hashCode() {  
int h = hash;  
       int len = count;  
if (h == 0 && len > 0) {  
    int off = offset;  
    char val[] = value;  

           for (int i = 0; i < len; i++) {  
               h = 31*h + val[off++];  
           }  
           hash = h;  
       }  
       return h;  
   }  
 /** 
    * Compares this string to the specified object.  The result is {@code 
    * true} if and only if the argument is not {@code null} and is a {@code 
    * String} object that represents the same sequence of characters as this 
    * object. 
    * 
    * @param  anObject 
    *         The object to compare this {@code String} against 
    * 
    * @return  {@code true} if the given object represents a {@code String} 
    *          equivalent to this string, {@code false} otherwise 
    * 
    * @see  #compareTo(String) 
    * @see  #equalsIgnoreCase(String) 
    */  
   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;  
   }  

4. 参考资料

  1. https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode()
  2. http://www.cnblogs.com/Qian123/p/5703507.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值