Chan Chen Coding...

          hashcode() and equal()

          equal方法 
          Object類的equals方法用于檢測(cè)一個(gè)對(duì)象是否等于另外一個(gè)對(duì)象,而Object類中這個(gè)方法的定義為兩個(gè)對(duì)象是否具有相同的引用。源碼如下: 
          Java代碼
          public boolean equals(Object obj) {  
              return (this == obj);  
              }  
          看起來沒有什么問題,兩個(gè)對(duì)象具有相同的引用,那這兩個(gè)對(duì)象一定是相等的,但在實(shí)際應(yīng)用中,這樣的比較其實(shí)并沒有什么實(shí)際意義,經(jīng)常發(fā)生的場(chǎng)景就是需要比較兩個(gè)對(duì)象的狀態(tài)的相等性,比如某個(gè)對(duì)象的唯一性標(biāo)識(shí)一致我們就認(rèn)為這兩個(gè)對(duì)象相等。java規(guī)范中對(duì)equal方法有如下要求 
          自反性:對(duì)于任何非空引用x,x,equal(x)應(yīng)該返回true 
          對(duì)稱性:對(duì)于任何引用x,x如果x.equal(y)返回true,那么y.equal(x)也應(yīng)該返回true 
          傳遞性:對(duì)于任何x,y,z,如果x.equal(y)返回true,y.equal(z)返回true,那么z.equal(x)返回true也應(yīng)該返回true。 
          一致性:如果x,y的引用沒有發(fā)生變化,那么反復(fù)調(diào)用equal方法應(yīng)該返回同樣的結(jié)果 
          非空性:對(duì)于任意非空引用x,x.equal(null)都應(yīng)該返回false 
          為了滿足實(shí)際需要,這個(gè)時(shí)候我們就需要重寫equal方法,針對(duì)規(guī)范,比較典型的寫法如下: 
          Java代碼 
          /** 
               * 
          @author GraMind 
               * 
          @param obj 
               * 
          @return 
               * 
          @exception  
               * 
          @see java.lang.Object#equals(java.lang.Object) 
               
          */  
              @Override  
              public boolean equals(Object obj)  
              {  
                  if (this == obj)                                         1  
                      return true;  
                  if (obj == null)                                         2  
                      return false;  
                  if (getClass() != obj.getClass())                        3  
                      return false;  
                  ClassName other = (ClassName) obj;                       4  
                  if (id != other.id)                                      5  
                      return false;  
                  .  
                  return true;  
              }  

          對(duì)于上面的代碼 
          1)檢測(cè)兩者是否引用同一個(gè)對(duì)象 
          2)檢測(cè)object是否為null,如果為null直接返回false 
          3)避免父子類引用相同的域(比如上類父子都具有id屬性),比較是否屬于同一級(jí)類,如果每個(gè)子類都具有統(tǒng)一的語義也可以使用instanceof來檢測(cè) 
          4)轉(zhuǎn)換要比較的類為對(duì)應(yīng)的類類型變量 
          5)根據(jù)需要比較相應(yīng)的域 
          注意:如果在子類中重寫了equal方法,就要在其中包含super.equal(...)。 
          散列碼 
          散列碼是有對(duì)象導(dǎo)出來的一個(gè)整形值,且沒有規(guī)律。如果重寫equal方法那么就必須重寫hashCode方法 
          想要明白為什么這樣做,你必須要先知道Java中的集合?! ?nbsp;
          總的來說,Java中的集合(Collection)有兩類,一類是List,再有一類是Set。 
          你知道它們的區(qū)別嗎?前者集合內(nèi)的元素是有序的,元素可以重復(fù);后者元素?zé)o序,但元素不可重復(fù)。 
          那么這里就有一個(gè)比較嚴(yán)重的問題了:要想保證元素不重復(fù),可兩個(gè)元素是否重復(fù)應(yīng)該依據(jù)什么來判斷呢? 
          這就是Object.equals方法了。但是,如果每增加一個(gè)元素就檢查一次,那么當(dāng)元素很多時(shí),后添加到集合中的元素比較的次數(shù)就非常多了。 
          也就是說,如果集合中現(xiàn)在已經(jīng)有1000個(gè)元素,那么第1001個(gè)元素加入集合時(shí),它就要調(diào)用1000次equals方法。這顯然會(huì)大大降低效率。    
          于是,Java采用了哈希表的原理。哈希(Hash)實(shí)際上是個(gè)人名,由于他提出一哈希算法的概念,所以就以他的名字命名了。 
          哈希算法也稱為散列算法,是將數(shù)據(jù)依特定算法直接指定到一個(gè)地址上。 
          初學(xué)者可以這樣理解,hashCode方法實(shí)際上返回的就是對(duì)象存儲(chǔ)的物理地址(實(shí)際可能并不是,比如大家可以看下String的hashCode實(shí)現(xiàn))。   
          這樣一來,當(dāng)集合要添加新的元素時(shí),先調(diào)用這個(gè)元素的hashCode方法,就一下子能定位到它應(yīng)該放置的物理位置上。 
          如果這個(gè)位置上沒有元素,它就可以直接存儲(chǔ)在這個(gè)位置上,不用再進(jìn)行任何比較了;如果這個(gè)位置上已經(jīng)有元素了, 
          就調(diào)用它的equals方法與新元素進(jìn)行比較,相同的話就不存了,不相同就散列其它的地址。 
          所以這里存在一個(gè)沖突解決的問題。這樣一來實(shí)際調(diào)用equals方法的次數(shù)就大大降低了,幾乎只需要一兩次。   
          所以,Java對(duì)于eqauls方法和hashCode方法是這樣規(guī)定的: 
          1、如果兩個(gè)對(duì)象相同,那么它們的hashCode值一定要相同;2、如果兩個(gè)對(duì)象的hashCode相同,它們并不一定相同     上面說的對(duì)象相同指的是用eqauls方法比較。 

          -----------------------------------------------------
          Silence, the way to avoid many problems;
          Smile, the way to solve many problems;

          posted on 2012-11-03 11:00 Chan Chen 閱讀(293) 評(píng)論(0)  編輯  收藏 所屬分類: Scala / Java

          主站蜘蛛池模板: 韶山市| 宁陕县| 和顺县| 广德县| 庆安县| 满城县| 绍兴县| 会理县| 阿坝| 广河县| 齐齐哈尔市| 赤壁市| 潼南县| 景宁| 平利县| 天等县| 宣城市| 深泽县| 云林县| 长宁县| 武汉市| 苏尼特右旗| 偏关县| 华亭县| 无为县| 河北省| 小金县| 石城县| 都江堰市| 宜阳县| 商洛市| 财经| 宜春市| 元谋县| 大宁县| 巴彦县| 扶绥县| 扎囊县| 蒲城县| 东城区| 凉山|