Java基礎之:集合——Map——HashMap
HashMap簡單介紹
-
Map介面的常用實作類:HashMap、Hashtable和Properties,
-
HashMap是 Map 介面使用頻率最高的實作類,
-
HashMap 是以 key-val 對的方式來存盤資料 [案例 Entry ]
-
key 不能重復,但是是值可以重復,允許使用null鍵和null值,
-
如果添加相同的key , 則會覆寫原來的key-val ,等同于修改.(key不會替換,val會替換)
-
與HashSet一樣,不保證映射的順序,因為底層是以hash表的方式來存盤的.
-
HashMap沒有實作同步,因此是執行緒不安全的,檔案 The HashMap class is roughly equivalent to Hashtable, except that it is unsynchronized and permits nulls.)
關于HashMap的案例,就是上一篇博客中描述Map的案例,使用的是HashMap,
HashMap底層機制

(k,v)是一個Node節點,實作了Map.Entry<K,V>,
jdk7.0的hashmap 底層實作[陣列+鏈表], jdk8.0 底層[陣列+ 鏈表/紅黑樹]
這里的鏈表都只有next屬性,沒有prev屬性,即單向鏈表,
擴容機制
table表的擴容機制(即上圖中第一行類似陣列的表):
-
HashMap底層維護了Node型別的陣列table,默認為null
-
當創建物件時,將加載因子(loadfactor)初始化為0.75
-
當添加元素時(呼叫putVal方法),需要通過該元素的哈希值獲取在table中的索引,然后判斷該索引處是否有元素,如果沒有元素直接添加,如果該索引處有元素,需要繼續判斷是否相等,如果相等則直接覆寫,如果不相等則需要判斷此時是樹結構還是鏈表結構,做相應處理,如果添加時發現容量不夠就需要擴容,
-
如果第一次添加,則需擴容table容量為16,臨界值(threshold)為12.(16 * 0.75 = 12)
-
即當table表的內容增長到臨界值(threshold)時,就會自動擴容,(添加第13個元素進入table表時,擴容)
-
如果其他次添加則需擴容table容量到原來的2倍,臨界值也改為原來的兩倍,(例:第2次擴容,table -> 32 , threshold -> 24)
table表中單個索引位置的擴容機制(鏈表/紅黑樹):
-
在table表中,一開始默認是長度為16的陣列
-
當某一個索引中的元素超過了8時,它優先會選擇將長度擴容2倍(即長度為32)的陣列,
-
它會認為是不是由于陣列的長度不夠才導致一個索引中元素過多,
-
但當它發現長度為32時,某一個索引中的元素還是超過9時,它還是會優先選擇將長度再次擴容到2倍(即長度為64)的陣列,
-
在長度為64的陣列中,它發現某一個索引中的元素還是超過10時,它就會對該索引所在的鏈表轉化為紅黑二叉樹.
-
所以在第十一個元素時,才會對該索引所在的鏈表轉化為紅黑二叉樹.
測驗代碼
import java.util.HashMap;
public class HashMapTreeNode {
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void main(String[] args) {
?
HashMap map = new HashMap();
?
for (int i = 1; i <= 20; i++) {
User user = new User();
?
map.put(user, user);
?
System.out.println("i =" + i);
}
}
}
?
class User {
?
// 保證每個元素放入同一個索引,將hashcode設定為1
@Override
public int hashCode() {
return 1;
}
?
// 保證在同一個索引中,每個元素不會因為相同被覆寫,將equles設定為false
@Override
public boolean equals(Object obj) {
return false;
}
}
?
LinkedHashMap
LinkedHashMap繼承自HashMap,包含了HashMap的所有機制,但不同的是LinkedHashMap是有序的(即添加和取出順序相同).
簡單案例:
package class_HashMap;
?
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
?
public class ClassTest01_LinkedHashMap {
?
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void main(String[] args) {
?
HashMap map = new LinkedHashMap();
map.put("1", "hello01");
map.put("2", "hello02");
map.put("3", "hello03");
map.put("3", "hello05");
map.put("4", "hello02");
map.put(null, "hello02");
map.put("5", null);
//遍歷鍵值對
Set entrySet = map.entrySet();
Iterator iterator = entrySet.iterator();
while(iterator.hasNext()) {
Object obj = iterator.next();
Map.Entry node = (Map.Entry)obj;
System.out.println(node.getKey() + " = " + node.getValue());
}
iterator = entrySet.iterator();
}
?
}
程式輸出:
1 = hello01
2 = hello02
3 = hello05
4 = hello02
null = hello02
5 = null
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/241201.html
標籤:Java

