HashSet、Hashtable與HashMap的關係

HashSet、Hashtable與HashMap的關係

一.HashSet與HashMap的關係

 

       閱讀HashSet的源代碼,發現加上很多註釋總共就只有300多行,所以就可以猜到它的內部實現一定藉助了其他的數據結構。事實上,它就是在HashMap的基礎上實現的。在它的內部,包含了一個HashMap。

privatetransient HashMap<E,Object> map;

 

  它的構造方法其實也是直接調用了HashMap的構造方法。

 

publicHashSet() {

    map = new HashMap<>();

}

  再來看一看它的add方法。

 

publicboolean add(E e) {

        return map.put(e, PRESENT)==null;

    }

 

        其實就是調用了HashMap的put方法,key就是加入的e,value爲PRESENT,它是HashSet內部的一個成員變量,就是一個空的Object對象。

privatestatic final Object PRESENT = new Object();

 

       它是一個虛值,作用就是爲了作爲value與HashMap關聯。add方法的返回值類型是boolean。通過上次分析的HashMap源碼可以知道,當放入的key值在HashMap的table數組中不存在時,即沒有hash衝突時,會把新元素加入數組中,同時返回null.所以這種情況下,add方法的返回值就是ture,表示進行了增加的操作。當放入的key,即HashSet要加入的e已經在HashMap的table數組中存在時,會用新的value覆蓋舊的value,對於HashSet來說,就是用新的PRESENT替換了舊的PRESENT。然後直接返回舊的value值,並沒有進行HashMap的插入操作。所以這個時候的add方法放入返回值就是false,表示HashSet沒有大小以及元素的改變。

 

       相似的,HashSet的remove方法也是直接調用了HashMap的remove方法

publicboolean remove(Object o) {

        return map.remove(o)==PRESENT;

    }

 

       由於HashMap的remove方法當size爲0或者要刪除的元素不存在時,會返回null,所以這時add方法的返回值就是false,表示沒有進行刪除的操作,HashSet沒有發生改變。當要刪除的元素存在時,HashMap的remove方法會返回value的值,由於在HashSet中,所有的value都是PRESENT這一個對象,所以這個時候add的返回值就是true,表示HashSet進行了刪除的操作,發生了改變。

 

 

二.Hashtable與HashMap的關係

   

      首先發現一個比較有趣的細節問題,就是Hashtable的t沒有大寫,沒有遵循java類命名的駝峯規則。不知道什麼原因。

然後一個比較大的區別是他們的父類不同。

HashMap<K,V>  extendsAbstractMap<K,V>

Hashtable<K,V>  extendsDictionary<K,V>

 

        他們的底層實現都是Entry數組,但是他們的初始默認的大小不一樣,HashMap中默認的大小是16,而Hashtable的默認大小確是11,但是他們的默認負載因子都是0.75.下面爲他的無參的構造方法:

public Hashtable() {

        this(11, 0.75f);

    }

 

        然後他們的求數組下標的哈希映射的算法實現不一樣,HashMap使用的是&運算,效率相對要高一些。而Hashtable使用的是取模的餘數運算。

int index = (hash & 0x7FFFFFFF) % tab.length;

 

 

          他們最大的區別就是Hashtable中所有的可能導致線程安全問題的方法都使用了synchronized修飾,加了互斥鎖。所以說Hashtable是線程安全的。但是缺點就是效率很低。他們的區別就好像Vector和ArrayList。他們還有很多的細節上的區別,大家無聊的時候可以去看看。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章