欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Java中用于查找對(duì)象哈希碼值的hashCode()函數(shù)

 更新時(shí)間:2016年05月27日 08:59:12   作者:馮立彬  
Java中入HashMap等一些鍵值對(duì)應(yīng)的結(jié)構(gòu),基本上都可以用hashCode()來查找值,接下來我們就來詳解Java中用于查找對(duì)象哈希碼值的hashCode()函數(shù):

理解
hashCode() 的作用是獲取哈希碼,也稱為散列碼;它實(shí)際上是返回一個(gè)int整數(shù)。這個(gè)哈希碼的作用是確定該對(duì)象在哈希表中的索引位置。
hashCode() 定義在JDK的Object.java中,這就意味著Java中的任何類都包含有hashCode() 函數(shù)。
雖然,每個(gè)Java類都包含hashCode() 函數(shù)。但是,僅僅當(dāng)創(chuàng)建并某個(gè)“類的散列表”(關(guān)于“散列表”見下面說明)時(shí),該類的hashCode() 才有用(作用是:確定該類的每一個(gè)對(duì)象在散列表中的位置;其它情況下(例如,創(chuàng)建類的單個(gè)對(duì)象,或者創(chuàng)建類的對(duì)象數(shù)組等等),類的hashCode() 沒有作用。
上面的散列表,指的是:Java集合中本質(zhì)是散列表的類,如HashMap,Hashtable,HashSet。
也就是說:hashCode() 在散列表中才有用,在其它情況下沒用。在散列表中hashCode() 的作用是獲取對(duì)象的散列碼,進(jìn)而確定該對(duì)象在散列表中的位置。
我們都知道,散列表存儲(chǔ)的是鍵值對(duì)(key-value),它的特點(diǎn)是:能根據(jù)“鍵”快速的檢索出對(duì)應(yīng)的“值”。這其中就利用到了散列碼!
散列表的本質(zhì)是通過數(shù)組實(shí)現(xiàn)的。當(dāng)我們要獲取散列表中的某個(gè)“值”時(shí),實(shí)際上是要獲取數(shù)組中的某個(gè)位置的元素。而數(shù)組的位置,就是通過“鍵”來獲取的;更進(jìn)一步說,數(shù)組的位置,是通過“鍵”對(duì)應(yīng)的散列碼計(jì)算得到的。
下面,我們以HashSet為例,來深入說明hashCode()的作用。
假設(shè),HashSet中已經(jīng)有1000個(gè)元素。當(dāng)插入第1001個(gè)元素時(shí),需要怎么處理?因?yàn)镠ashSet是Set集合,它允許有重復(fù)元素。
“將第1001個(gè)元素逐個(gè)的和前面1000個(gè)元素進(jìn)行比較”?顯然,這個(gè)效率是相等低下的。散列表很好的解決了這個(gè)問題,它根據(jù)元素的散列碼計(jì)算出元素在散列表中的位置,然后將元素插入該位置即可。對(duì)于相同的元素,自然是只保存了一個(gè)。
由此可知,若兩個(gè)元素相等,它們的散列碼一定相等;但反過來確不一定。在散列表中,
1、如果兩個(gè)對(duì)象相等,那么它們的hashCode()值一定要相同;
2、如果兩個(gè)對(duì)象hashCode()相等,它們并不一定相等。
注意:這是在散列表中的情況。在非散列表中一定如此!

示例
我們來看一個(gè)具體的示例吧,

public class HashTest { 
  private int i; 
 
  public int getI() { 
    return i; 
  } 
 
  public void setI(int i) { 
    this.i = i; 
  } 
 
  public int hashCode() { 
    return i % 10; 
  } 
 
  public final static void main(String[] args) { 
    HashTest a = new HashTest(); 
    HashTest b = new HashTest(); 
    a.setI(1); 
    b.setI(1); 
    Set<HashTest> set = new HashSet<HashTest>(); 
    set.add(a); 
    set.add(b); 
    System.out.println(a.hashCode() == b.hashCode()); 
    System.out.println(a.equals(b)); 
    System.out.println(set); 
  } 
} 

這個(gè)輸出的結(jié)果:

true 
false 
[com.ubs.sae.test.HashTest@1, com.ubs.sae.test.HashTest@1] 

以上這個(gè)示例,我們只是重寫了hashCode方法,從上面的結(jié)果可以看出,雖然兩個(gè)對(duì)象的hashCode相等,但是實(shí)際上兩個(gè)對(duì)象并不是相等;,我們沒有重寫equals方法,那么就會(huì)調(diào)用object默認(rèn)的equals方法,是比較兩個(gè)對(duì)象的引用是不是相同,顯示這是兩個(gè)不同的對(duì)象,兩個(gè)對(duì)象的引用肯定是不定的。這里我們將生成的對(duì)象放到了HashSet中,而HashSet中只能夠存放唯一的對(duì)象,也就是相同的(適用于equals方法)的對(duì)象只會(huì)存放一個(gè),但是這里實(shí)際上是兩個(gè)對(duì)象a,b都被放到了HashSet中,這樣HashSet就失去了他本身的意義了。
此時(shí)我們把equals方法給加上:

public class HashTest { 
  private int i; 
 
  public int getI() { 
    return i; 
  } 
 
  public void setI(int i) { 
    this.i = i; 
  } 
 
  <span style="color:#3366FF;"><strong>public boolean equals(Object object) { 
    if (object == null) { 
      return false; 
    } 
    if (object == this) { 
      return true; 
    } 
    if (!(object instanceof HashTest)) { 
      return false; 
    } 
    HashTest other = (HashTest) object; 
    if (other.getI() == this.getI()) { 
      return true; 
    } 
    return false; 
  }</strong></span> 
 
  public int hashCode() { 
    return i % 10; 
  } 
 
  public final static void main(String[] args) { 
    HashTest a = new HashTest(); 
    HashTest b = new HashTest(); 
    a.setI(1); 
    b.setI(1); 
    Set<HashTest> set = new HashSet<HashTest>(); 
    set.add(a); 
    set.add(b); 
    System.out.println(a.hashCode() == b.hashCode()); 
    System.out.println(a.equals(b)); 
    System.out.println(set); 
  } 
} 

此時(shí)得到的結(jié)果就會(huì)如下:

true 
true 
[com.ubs.sae.test.HashTest@1] 

從結(jié)果我們可以看出,現(xiàn)在兩個(gè)對(duì)象就完全相等了,HashSet中也只存放了一份對(duì)象。

總結(jié)
1、hashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,hashCode是用來在散列存儲(chǔ)結(jié)構(gòu)中確定對(duì)象的存儲(chǔ)地址的;

2、如果兩個(gè)對(duì)象相同,就是適用于equals(java.lang.Object) 方法,那么這兩個(gè)對(duì)象的hashCode一定要相同;

3、如果對(duì)象的equals方法被重寫,那么對(duì)象的hashCode也盡量重寫,并且產(chǎn)生hashCode使用的對(duì)象,一定要和equals方法中使用的一致,否則就會(huì)違反上面提到的第2點(diǎn);

4、兩個(gè)對(duì)象的hashCode相同,并不一定表示兩個(gè)對(duì)象就相同,也就是不一定適用于equals(java.lang.Object) 方法,只能夠說明這兩個(gè)對(duì)象在散列存儲(chǔ)結(jié)構(gòu)中,如Hashtable,他們“存放在同一個(gè)籃子里”。

相關(guān)文章

最新評(píng)論