qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請訪問 http://qaseven.github.io/

          淺談Java中的hashcode方法

           哈希表這個數(shù)據(jù)結(jié)構(gòu)想必大多數(shù)人都不陌生,而且在很多地方都會利用到hash表來提高查找效率。在Java的Object類中有一個方法:
            public native int hashCode();
            根據(jù)這個方法的聲明可知,該方法返回一個int類型的數(shù)值,并且是本地方法,因此在Object類中并沒有給出具體的實現(xiàn)。
            為何Object類需要這樣一個方法?它有什么作用呢?今天我們就來具體探討一下hashCode方法。
            一.hashCode方法的作用
            對于包含容器類型的程序設(shè)計語言來說,基本上都會涉及到hashCode。在Java中也一樣,hashCode方法的主要作用是為了配合基于散列的集合一起正常運(yùn)行,這樣的散列集合包括HashSet、HashMap以及HashTable。
            為什么這么說呢?考慮一種情況,當(dāng)向集合中插入對象時,如何判別在集合中是否已經(jīng)存在該對象了?(注意:集合中不允許重復(fù)的元素存在)
            也許大多數(shù)人都會想到調(diào)用equals方法來逐個進(jìn)行比較,這個方法確實可行。但是如果集合中已經(jīng)存在一萬條數(shù)據(jù)或者更多的數(shù)據(jù),如果采用equals方法去逐一比較,效率必然是一個問題。此時hashCode方法的作用就體現(xiàn)出來了,當(dāng)集合要添加新的對象時,先調(diào)用這個對象的hashCode方法,得到對應(yīng)的hashcode值,實際上在HashMap的具體實現(xiàn)中會用一個table保存已經(jīng)存進(jìn)去的對象的hashcode值,如果table中沒有該hashcode值,它就可以直接存進(jìn)去,不用再進(jìn)行任何比較了;如果存在該hashcode值, 就調(diào)用它的equals方法與新元素進(jìn)行比較,相同的話就不存了,不相同就散列其它的地址,所以這里存在一個沖突解決的問題,這樣一來實際調(diào)用equals方法的次數(shù)就大大降低了,說通俗一點:Java中的hashCode方法就是根據(jù)一定的規(guī)則將與對象相關(guān)的信息(比如對象的存儲地址,對象的字段等)映射成一個數(shù)值,這個數(shù)值稱作為散列值。下面這段代碼是java.util.HashMap的中put方法的具體實現(xiàn):
          public V put(K key, V value) {
          if (key == null)
          return putForNullKey(value);
          int hash = hash(key.hashCode());
          int i = indexFor(hash, table.length);
          for (Entry<K,V> e = table[i]; e != null; e = e.next) {
          Object k;
          if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
          V oldValue = e.value;
          e.value = value;
          e.recordAccess(this);
          return oldValue;
          }
          }
          modCount++;
          addEntry(hash, key, value, i);
          return null;
          }
            put方法是用來向HashMap中添加新的元素,從put方法的具體實現(xiàn)可知,會先調(diào)用hashCode方法得到該元素的hashCode值,然后查看table中是否存在該hashCode值,如果存在則調(diào)用equals方法重新確定是否存在該元素,如果存在,則更新value值,否則將新的元素添加到HashMap中。從這里可以看出,hashCode方法的存在是為了減少equals方法的調(diào)用次數(shù),從而提高程序效率。
            有些朋友誤以為默認(rèn)情況下,hashCode返回的就是對象的存儲地址,事實上這種看法是不全面的,確實有些JVM在實現(xiàn)時是直接返回對象的存儲地址,但是大多時候并不是這樣。
            因此有人會說,可以直接根據(jù)hashcode值判斷兩個對象是否相等嗎?肯定是不可以的,因為不同的對象可能會生成相同的hashcode值。雖然不能根據(jù)hashcode值判斷兩個對象是否相等,但是可以直接根據(jù)hashcode值判斷兩個對象不等,如果兩個對象的hashcode值不等,則必定是兩個不同的對象。如果要判斷兩個對象是否真正相等,必須通過equals方法。
            也就是說對于兩個對象,如果調(diào)用equals方法得到的結(jié)果為true,則兩個對象的hashcode值必定相等;
            如果equals方法得到的結(jié)果為false,則兩個對象的hashcode值不一定不同;
            如果兩個對象的hashcode值不等,則equals方法得到的結(jié)果必定為false;
            如果兩個對象的hashcode值相等,則equals方法得到的結(jié)果未知。

          posted on 2014-05-29 11:36 順其自然EVO 閱讀(147) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          <2014年5月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          導(dǎo)航

          統(tǒng)計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 屏山县| 册亨县| 留坝县| 嫩江县| 丽江市| 菏泽市| 湟中县| 武汉市| 浮山县| 广昌县| 汤阴县| 马龙县| 涞源县| 安达市| 塔河县| 武强县| 安平县| 香格里拉县| 象山县| 莱西市| 凤城市| 唐山市| 石景山区| 酉阳| 文山县| 景德镇市| 阿坝| 永顺县| 桦甸市| 麦盖提县| 谢通门县| 濮阳县| 延边| 安福县| 姚安县| 五寨县| 临湘市| 温泉县| 泾源县| 沙河市| 宽城|