zoukankan      html  css  js  c++  java
  • Java中hashCode的作用

     

    原创 2013年05月09日 13:54:53

    以下是关于HashCode的官方文档定义:

    [plain] view plain copy
     
    1. hashcode方法返回该对象的哈希码值。支持该方法是为哈希表提供一些优点,例如,java.util.Hashtable 提供的哈希表。   
    2.   
    3. hashCode 的常规协定是:   
    4. 在 Java 应用程序执行期间,在同一对象上多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是对象上 equals 比较中所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。   
    5. 如果根据 equals(Object) 方法,两个对象是相等的,那么在两个对象中的每个对象上调用 hashCode 方法都必须生成相同的整数结果。   
    6. 以下情况不 是必需的:如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么在两个对象中的任一对象上调用 hashCode 方法必定会生成不同的整数结果。但是,程序员应该知道,为不相等的对象生成不同整数结果可以提高哈希表的性能。   
    7. 实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)   
    8.   
    9. 当equals方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。  

    以上这段官方文档的定义,我们可以抽出成以下几个关键点:

    1、hashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,hashCode是用来在散列存储结构中确定对象的存储地址的;

    2、如果两个对象相同,就是适用于equals(java.lang.Object) 方法,那么这两个对象的hashCode一定要相同;

    3、如果对象的equals方法被重写,那么对象的hashCode也尽量重写,并且产生hashCode使用的对象,一定要和equals方法中使用的一致,否则就会违反上面提到的第2点;

    4、两个对象的hashCode相同,并不一定表示两个对象就相同,也就是不一定适用于equals(java.lang.Object) 方法,只能够说明这两个对象在散列存储结构中,如Hashtable,他们“存放在同一个篮子里”

    再归纳一下就是hashCode是用于查找使用的,而equals是用于比较两个对象的是否相等的。以下这段话是从别人帖子回复拷贝过来的:

    [plain] view plain copy
     
    1. 1.hashcode是用来查找的,如果你学过数据结构就应该知道,在查找和排序这一章有  
    2. 例如内存中有这样的位置  
    3. 0  1  2  3  4  5  6  7    
    4. 而我有个类,这个类有个字段叫ID,我要把这个类存放在以上8个位置之一,如果不用hashcode而任意存放,那么当查找时就需要到这八个位置里挨个去找,或者用二分法一类的算法。  
    5. 但如果用hashcode那就会使效率提高很多。  
    6. 我们这个类中有个字段叫ID,那么我们就定义我们的hashcode为ID%8,然后把我们的类存放在取得得余数那个位置。比如我们的ID为9,9除8的余数为1,那么我们就把该类存在1这个位置,如果ID是13,求得的余数是5,那么我们就把该类放在5这个位置。这样,以后在查找该类时就可以通过ID除 8求余数直接找到存放的位置了。  
    7.   
    8. 2.但是如果两个类有相同的hashcode怎么办那(我们假设上面的类的ID不是唯一的),例如9除以8和17除以8的余数都是1,那么这是不是合法的,回答是:可以这样。那么如何判断呢?在这个时候就需要定义 equals了。  
    9. 也就是说,我们先通过 hashcode来判断两个类是否存放某个桶里,但这个桶里可能有很多类,那么我们就需要再通过 equals 来在这个桶里找到我们要的类。  
    10. 那么。重写了equals(),为什么还要重写hashCode()呢?  
    11. 想想,你要在一个桶里找东西,你必须先要找到这个桶啊,你不通过重写hashcode()来找到桶,光重写equals()有什么用啊  


    最后,我们来看一个具体的示例吧,

    [java] view plain copy
     
    1. public class HashTest {  
    2.     private int i;  
    3.   
    4.     public int getI() {  
    5.         return i;  
    6.     }  
    7.   
    8.     public void setI(int i) {  
    9.         this.i = i;  
    10.     }  
    11.   
    12.     public int hashCode() {  
    13.         return i % 10;  
    14.     }  
    15.   
    16.     public final static void main(String[] args) {  
    17.         HashTest a = new HashTest();  
    18.         HashTest b = new HashTest();  
    19.         a.setI(1);  
    20.         b.setI(1);  
    21.         Set<HashTest> set = new HashSet<HashTest>();  
    22.         set.add(a);  
    23.         set.add(b);  
    24.         System.out.println(a.hashCode() == b.hashCode());  
    25.         System.out.println(a.equals(b));  
    26.         System.out.println(set);  
    27.     }  
    28. }  

    这个输出的结果:
    [plain] view plain copy
     
    1. true  
    2. false  
    3. [com.ubs.sae.test.HashTest@1, com.ubs.sae.test.HashTest@1]  

    以上这个示例,我们只是重写了hashCode方法,从上面的结果可以看出,虽然两个对象的hashCode相等,但是实际上两个对象并不是相等;,我们没有重写equals方法,那么就会调用object默认的equals方法,是比较两个对象的引用是不是相同,显示这是两个不同的对象,两个对象的引用肯定是不定的。这里我们将生成的对象放到了HashSet中,而HashSet中只能够存放唯一的对象,也就是相同的(适用于equals方法)的对象只会存放一个,但是这里实际上是两个对象a,b都被放到了HashSet中,这样HashSet就失去了他本身的意义了。

    此时我们把equals方法给加上:

    [java] view plain copy
     
    1. public class HashTest {  
    2.     private int i;  
    3.   
    4.     public int getI() {  
    5.         return i;  
    6.     }  
    7.   
    8.     public void setI(int i) {  
    9.         this.i = i;  
    10.     }  
    11.   
    12.     <span style="color:#3366FF;"><strong>public boolean equals(Object object) {  
    13.         if (object == null) {  
    14.             return false;  
    15.         }  
    16.         if (object == this) {  
    17.             return true;  
    18.         }  
    19.         if (!(object instanceof HashTest)) {  
    20.             return false;  
    21.         }  
    22.         HashTest other = (HashTest) object;  
    23.         if (other.getI() == this.getI()) {  
    24.             return true;  
    25.         }  
    26.         return false;  
    27.     }</strong></span>  
    28.   
    29.     public int hashCode() {  
    30.         return i % 10;  
    31.     }  
    32.   
    33.     public final static void main(String[] args) {  
    34.         HashTest a = new HashTest();  
    35.         HashTest b = new HashTest();  
    36.         a.setI(1);  
    37.         b.setI(1);  
    38.         Set<HashTest> set = new HashSet<HashTest>();  
    39.         set.add(a);  
    40.         set.add(b);  
    41.         System.out.println(a.hashCode() == b.hashCode());  
    42.         System.out.println(a.equals(b));  
    43.         System.out.println(set);  
    44.     }  
    45. }  
    此时得到的结果就会如下:
    [plain] view plain copy
     
    1. true  
    2. true  
    3. [com.ubs.sae.test.HashTest@1]  

    从结果我们可以看出,现在两个对象就完全相等了,HashSet中也只存放了一份对象。
  • 相关阅读:
    HDU 5528 Count a * b 欧拉函数
    HDU 5534 Partial Tree 完全背包
    HDU 5536 Chip Factory Trie
    HDU 5510 Bazinga KMP
    HDU 4821 String 字符串哈希
    HDU 4814 Golden Radio Base 模拟
    LA 6538 Dinner Coming Soon DP
    HDU 4781 Assignment For Princess 构造
    LA 7056 Colorful Toy Polya定理
    LA 6540 Fibonacci Tree
  • 原文地址:https://www.cnblogs.com/www123----/p/7857110.html
Copyright © 2011-2022 走看看