1枫匾、講這兩者之前先講一講 ==哑芹,equals() 與hashcode()之間的關(guān)系
1.1 ==對于java中基本數(shù)據(jù)類型變量就是比較變量值花盐;對于非基本數(shù)據(jù)類型類型执虹,比較的是對象在內(nèi)存中的地址拓挥;
1.2 equals()是所有類(所有類都繼承自O(shè)bject)中都含有的一個方法,當(dāng)沒有重寫equals()方法時袋励,equals()等價于==也是判斷內(nèi)存地址是否相同侥啤,重寫的情況下往往用來判斷屬性是否相同当叭;
1.3 hashcode()也是每個類(Object類中的方法)都有的方法,當(dāng)不重寫該方法時盖灸,某些jvm會將內(nèi)存地址作為返回值蚁鳖。
1.4 因為Java的集合需要存取對象時,是要根據(jù)對象的hashcode方法的返回值來確定對象是否相同赁炎,所以要保證你的類使用Java集合不出異常的話醉箕,我們必須遵循以下規(guī)則:
1)當(dāng)兩個對象equals()比較相同時,它們的hashcode()返回值也一定相同徙垫;
2)當(dāng)兩個對象hashcode()返回值相同時讥裤,它們equals()比較未必相同;
1.5 重寫hashcode()方法也很簡單姻报,往往通過計算相關(guān)字段的哈希碼己英,再把這些哈希碼組合起來得到哈希碼。
舉個例子:
@Override
public int hashcode(){
return Objects.hash(firstName, lastName);
}
2吴旋、現(xiàn)在進入正題损肛,來說說HashMap與Hashtable的區(qū)別
2.1 HashMap幾乎可以等價于Hashtable,除了HashMap是非synchronized的荣瑟,并可以接受null(HashMap可以接受為null的鍵值(key)和值(value)治拿,而Hashtable則不行)。
2.2 HashMap是非synchronized笆焰,而Hashtable是synchronized忍啤,這意味著Hashtable是線程安全的,多個線程可以共享一個Hashtable仙辟;而如果沒有正確的同步的話,多個線程是不能共享HashMap的鳄梅。
2.3 由于Hashtable是線程安全的也是synchronized叠国,所以在單線程環(huán)境下它比HashMap要慢。如果你不需要同步戴尸,只需要單一線程粟焊,那么使用HashMap性能要好過Hashtable。
2.4 HashMap可以通過下面的語句進行同步:
Map m = Collections.synchronizeMap(hashMap);
3孙蒙、hashmap與hashtable的實現(xiàn)
3.1 初始容量大小和每次擴充容量大小
1)HashMap默認(rèn)的初始化大小為16项棠。之后每次擴充,容量變?yōu)樵瓉淼?倍挎峦。
2)Hashtable默認(rèn)的初始大小為n香追,之后每次擴充,容量變?yōu)樵瓉淼?n+1坦胶;
HashMap的初始大小固定為16透典,而Hashtable由你給定晴楔。
之所以會有這樣的不同,是因為Hashtable和HashMap設(shè)計時的側(cè)重點不同峭咒。Hashtable的側(cè)重點是哈希的結(jié)果更加均勻税弃,使得哈希沖突減少。當(dāng)哈希表的大小為素數(shù)時凑队,簡單的取模哈希的結(jié)果會更加均勻则果。而HashMap則更加關(guān)注hash的計算效率問題。在取模計算時漩氨,如果模數(shù)是2的冪西壮,那么我們可以直接使用位運算來得到結(jié)果,效率要大大高于做除法才菠。HashMap為了加快hash的速度茸时,將哈希表的大小固定為了2的冪。當(dāng)然這引入了哈希分布不均勻的問題赋访,所以HashMap為解決這問題可都,又對hash算法做了一些改動。這從而導(dǎo)致了Hashtable和HashMap的計算hash值的方法不同
3.2 計算hash值的方法
1)HashMap計算hash值的方法
int hash = key.hashCode();
int index = hash & map.length();
2)Hashtable計算hash值的方法
int hash = key.hashCode();
int index =( hash & 0x7FFFFFFF) % table.length();