久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

從HashCode出發(fā)介紹HashMap以及如何重寫自己的HashCode方法

 鬼迷心竅 2006-09-22
zt:從HashCode出發(fā)介紹HashMap以及如何重寫自己的HashCode方法

大家都知道,在Java里對對象的操作是基于引用的,。而當我們需要對一組對象操作的時候,,就需要有接收這一組引用的容器。平時我們最常用的就是數(shù)組,。在Java里可以定義一個對象數(shù)組來完成許多操作,。可是,,數(shù)組長度是固定的,,如果我們需要更加靈活的解決方案該怎么辦呢?

Java提供了container classes來解決這一問題,。container classes包括兩個部分:Collection和Map,。

本文重點介紹HashMap。首先介紹一下什么是Map,。在數(shù)組中我們是通過數(shù)組下標來對其內(nèi)容索引的,,而在Map中我們通過對象來對對象進行索引,用來索引的對象叫做key,其對應的對象叫做value,。在下文中會有例子具體說明,。

再來看看HashMap和TreeMap有什么區(qū)別。HashMap通過hashcode對其內(nèi)容進行快速查找,,而TreeMap中所有的元素都保持著某種固定的順序,,如果你需要得到一個有序的結(jié)果你就應該使用TreeMap(HashMap中元素的排列順序是不固定的)。

下面就要進入本文的主題了,。先舉個例子說明一下怎樣使用HashMap:
import java.util.*;

public class Exp1 {
  public static void main(String[] args){
      HashMap h1=new HashMap();
      Random r1=new Random();  
      for(int i=0;i<1000;i++){
          Integer t=new Integer(r1.nextInt(20));
          if(h1.containsKey(t))
            ((Ctime)h1.get(t)).count++;
          else
            h1.put(t, new Ctime());
      }
      System.out.println(h1);
  }
}

class Ctime{
  int count=1;
  public String toString(){
      return Integer.toString(count);
  }
}

在HashMap中通過get()來獲取value,,通過put()來插入value,ContainsKey()則用來檢驗對象是否已經(jīng)存在,??梢钥闯觯虯rrayList的操作相比,,HashMap除了通過key索引其內(nèi)容之外,,別的方面差異并不大。

前面介紹了,,HashMap是基于HashCode的,在所有對象的超類Object中有一個HashCode()方法,,但是它和equals方法一樣,,并不能適用于所有的情況,這樣我們就需要重寫自己的HashCode()方法,。下面就舉這樣一個例子:
import java.util.*;

public class Exp2 {
  public static void main(String[] args){
      HashMap h2=new HashMap();
      for(int i=0;i<10;i++)
          h2.put(new Element(i), new Figureout());
      System.out.println("h2:");
      System.out.println("Get the result for Element:");
      Element test=new Element(5);
      if(h2.containsKey(test))
          System.out.println((Figureout)h2.get(test));
      else
          System.out.println("Not found");
  }
}

class Element{
  int number;
  public Element(int n){
      number=n;
  }
}

class Figureout{
  Random r=new Random();
  boolean possible=r.nextDouble()>0.5;
  public String toString(){
      if(possible)
          return "OK!";
      else
          return "Impossible!";
  }
}

在這個例子中,,Element用來索引對象Figureout,也即Element為key,F(xiàn)igureout為value,。在Figureout中隨機生成一個浮點數(shù),,如果它比0.5大,打印“OK!”,,否則打印“Impossible!”,。之后查看Element(3)對應的Figureout結(jié)果如何。

結(jié)果卻發(fā)現(xiàn),,無論你運行多少次,,得到的結(jié)果都是“Not found”。也就是說索引Element(3)并不在HashMap中,。這怎么可能呢,?

原因得慢慢來說:Element的HashCode方法繼承自Object,而Object中的HashCode方法返回的HashCode對應于當前的地址,,也就是說對于不同的對象,,即使它們的內(nèi)容完全相同,用HashCode()返回的值也會不同。這樣實際上違背了我們的意圖,。因為我們在使用 HashMap時,,希望利用相同內(nèi)容的對象索引得到相同的目標對象,這就需要HashCode()在此時能夠返回相同的值,。在上面的例子中,,我們期望 new Element(i) (i=5)與 Element test=new Element(5)是相同的,而實際上這是兩個不同的對象,,盡管它們的內(nèi)容相同,,但它們在內(nèi)存中的地址不同。因此很自然的,,上面的程序得不到我們設想的結(jié)果,。下面對Element類更改如下:
class Element{
  int number;
  public Element(int n){
      number=n;
  }
  public int hashCode(){
      return number;
  }
  public boolean equals(Object o){
      return (o instanceof Element) && (number==((Element)o).number);
  }
}

在這里Element覆蓋了Object中的hashCode()和equals()方法。覆蓋hashCode()使其以number的值作為 hashcode返回,,這樣對于相同內(nèi)容的對象來說它們的hashcode也就相同了,。而覆蓋equals()是為了在HashMap判斷兩個key是否相等時使結(jié)果有意義(有關(guān)重寫equals()的內(nèi)容可以參考我的另一篇文章《重新編寫Object類中的方法 》)。修改后的程序運行結(jié)果如下:

h2:
Get the result for Element:
Impossible!

請記?。喝绻阆胗行У氖褂肏ashMap,,你就必須重寫在其的HashCode()。

還有兩條重寫HashCode()的原則:

  1. 不必對每個不同的對象都產(chǎn)生一個唯一的hashcode,,只要你的HashCode方法使get()能夠得到put()放進去的內(nèi)容就可以了,。即“不為一原則”。
  2. 生成hashcode的算法盡量使hashcode的值分散一些,,不要很多hashcode都集中在一個范圍內(nèi),,這樣有利于提高HashMap的性能。即“分散原則”,。

至于第二條原則的具體原因,,有興趣者可以參考Bruce Eckel的《Thinking in Java》,在那里有對HashMap內(nèi)部實現(xiàn)原理的介紹,,這里就不贅述了,。

掌握了這兩條原則,你就能夠用好HashMap編寫自己的程序了,。不知道大家注意沒有,,java.lang.Object中提供的三個方法: clone(),equals()和hashCode()雖然很典型,,但在很多情況下都不能夠適用,,它們只是簡單的由對象的地址得出結(jié)果。這就需要我們在自己的程序中重寫它們,,其實java類庫中也重寫了千千萬萬個這樣的方法,。利用面向?qū)ο蟮亩鄳B(tài)性——覆蓋,,Java的設計者很優(yōu)雅的構(gòu)建了Java的結(jié)構(gòu),也更加體現(xiàn)了Java是一門純OOP語言的特性,。

Java提供的Collection和Map的功能是十分強大的,,它們能夠使你的程序?qū)崿F(xiàn)方式更為靈活,執(zhí)行效率更高,。希望本文能夠?qū)Υ蠹腋玫氖褂肏ashMap有所幫助,。

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多