亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

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

示例
我們來看一個具體的示例吧,

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); 
  } 
} 

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

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

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

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

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

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

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

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

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

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

相關(guān)文章

最新評論