1. 程式人生 > >Map與HashMap,Hashtable,HashSet的區別

Map與HashMap,Hashtable,HashSet的區別

前言:

自開始接手這JAVA寫的框架以來,遇到各種問題,發現與PYTHON,習慣真不一樣,在處理YAML資料時,用到hashmap,map等,各種糾結,幸虧得到,小林同學的幫忙,終於問題解決了,因此參考網路內容,順便總結下,這各種鬼的用法,當然,還是建議各位用PYTHON,PYTHON把各種型別轉換過程全給你做了

生命太短,你應該用PYTHON。

HashTable和HashMap區別

區別一:繼承的父類不同 
Hashtable繼承自Dictionary類,而HashMap繼承自AbstractMap類。但二者都實現了Map介面。

public class Hashtable<K
,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, Serializable public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable
  • 1
  • 2
  • 3
  • 4
  • 5

區別二:執行緒安全性不同 
Hashtable 中的方法是Synchronize的,而HashMap中的方法在預設情況下是非Synchronize的。

區別三:是否提供contains方法 
HashMap把Hashtable的contains方法去掉了,改成containsValue和containsKey,因為contains方法容易讓人引起誤解。 
Hashtable則保留了contains,containsValue和containsKey三個方法,其中contains和containsValue功能相同。

**區別四:**key和value是否允許null值 
其中key和value都是物件,並且不能包含重複key,但可以包含重複的value。 
Hashtable中,key和value都不允許出現null值。 
HashMap中,null可以作為鍵,這樣的鍵只有一個;可以有一個或多個鍵所對應的值為null。當get()方法返回null值時,可能是 HashMap中沒有該鍵,也可能使該鍵所對應的值為null。因此,在HashMap中不能由get()方法來判斷HashMap中是否存在某個鍵, 而應該用containsKey()方法來判斷。 
PS:這個面試喜歡問。

區別五:雜湊值的計算方法不同,Hashtable直接使用的是物件的hashCode,而HashMap則是在物件的hashCode的基礎上還進行了一些變化。

//Hashtable中可以看出的是直接採用關鍵字的hashcode作為雜湊值
    int hash = key.hashCode();
    //然後進行模運算,求出所在譁然表的位置 
    int index = (hash & 0x7FFFFFFF) % tab.length;
//HashMap中的實現
   //這兩行程式碼的意思是先計算hashcode,然後再求其在雜湊表的相應位置      
    int hash = hash(key.hashCode());
    int i = indexFor(hash, table.length);
    static int hash(int h) {
     // This function ensures that hashCodes that differ only by
     // constant multiples at each bit position have a bounded
     // number of collisions (approximately 8 at default load factor).
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }
   //求位於雜湊表中的位置
    static int indexFor(int h, int length) {
        return h & (length-1);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

區別六:內部實現使用的陣列初始化和擴容方式不同,記憶體初始大小不同,HashTable初始大小是11,而HashMap初始大小是16

     public Hashtable() {
                //從這裡可以看出,預設的初始化大小11,
                //這裡的11並不是11個位元組,而是11個       Entry,這個Entry是
                //實現連結串列的關鍵結構
                //這裡的0.75代表的是裝載因子
                this(11, 0.75f);
     }
    public HashMap() {
        //這個預設的裝載因子也是0.75
         this.loadFactor = DEFAULT_LOAD_FACTOR;
        //預設的痤為0.75*16
        threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
        //這裡開始是預設的初始化大小,這裡大小是16
        table = new Entry[DEFAULT_INITIAL_CAPACITY];
        init();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

Hashtable採用的是2*old+1,而HashMap是2*old

HashMap和HashSet的區別

HashSet實質

(1)HashSet是set的一個實現類,hashMap是Map的一個實現類,同時hashMap是hashTable的替代品(為什麼後面會講到). 
(2)HashSet以物件作為元素,而HashMap以(key-value)的一組物件作為元素,且HashSet拒絕接受重複的物件.HashMap可以看作三個檢視:key的Set,value的Collection,Entry的Set。 這裡HashSet就是其實就是HashMap的一個檢視。 
HashSet內部就是使用Hashmap實現的,和Hashmap不同的是它不需要Key和Value兩個值。 
往hashset中插入物件其實只不過是內部做了

      public boolean add(Object o) {
            return map.put(o, PRESENT)==null;
      }