HashMap深入學習

2021-08-22 03:10:48 字數 3948 閱讀 6843

一、簡介

hashmap是雜湊表的map實現,以key-value的形式儲存資料,根據hash演算法,使key-value分布均勻

二、資料結構

hashmap的資料結構在jdk1.7到1.8做了改進,jdk1.7採用陣列+鍊錶的結構,jdk1.8在1.7的基礎新增了紅黑樹,即陣列+鍊錶+紅黑樹。之所以加入紅黑樹的概念,是因為在多次雜湊衝突導致鍊錶太長時,自動轉換成紅黑樹,提高查詢效率。

三、常用方法

hashmap共有4個構造方法:

hashmap()

//預設構造方法

hashmap(map extends k, ? extends v> m)

//接收乙個map作為引數的構造方法,可以用乙個現有的map初始化乙個新的map

hashmap(int initialcapacity)

//帶初始容量的構造方法

hashmap(int initialcapacity, float loadfactor)

//帶初始容量和負載因子的構造方法

其他常用方法:

put(k key, v value)

//將key、value鍵值對放到hashmap中

putall(map extends k, ? extends v> m)

//將乙個map中所有元素全部放入此map中

get(object key)

//通過key獲取對應的value

remove(object key)

//通過key移除鍵值對

containskey(object key)

//當前map key的集合中是否含有傳入key

containsvalue(object value)

//當前map value的集合中是否含有傳入value

keyset()

//獲取key的集合

size()

// map所含元素個數(包含陣列+鏈結+紅黑樹中所有的鍵值對數量)

isempty()

//map是否為空

resize()

//擴容時用到,用來重新整理內部結構

clear()

//清空map

四、原始碼分析1.常用引數

//預設的初始化容量 16

static

final

int default_initial_capacity = 1

<< 4;

//最大容量,容量超過會以此容量為準,2的30次方

static

final

int maximum_capacity = 1

<< 30;

//預設的負載因子,跟hashmap的擴容有關

static

final

float default_load_factor = 0.75f;

//鍊錶轉成紅黑樹的節點數,當鍊表節點數達到8個時,會自動轉換成紅黑樹

static

final

int treeify_threshold = 8;

//紅黑樹轉成鍊錶的節點數,當節點數小於等於6時,自動從紅黑樹轉成鍊錶

static

final

int untreeify_threshold = 6;

//表的容量超過此閾值,桶才可以轉換成紅黑樹(陣列中的元素稱為桶)

static

final

int min_treeify_capacity = 64;

2.常用方法

put將鍵值對儲存到hashmap的基本過程:

1、第一次進行put操作時,呼叫resize()進行容量的初始化

2、通過hash演算法將key對映到資料中的某個元素中

3、如果陣列的當前元素中已經儲存了資料,此時便產生了hash衝突,需要將已經儲存在陣列中的資料移到表尾,新put的資料作為表頭,放到陣列的元素中

4、當hash衝突導致鍊錶的長度達到8,陣列中的元素會自動由鏈結轉換成紅黑樹,提高查詢效率

/**

*@param onlyifabsent 若為true,不會改變已經存在的value

**/final v putval(int hash, k key, v value, boolean onlyifabsent,

boolean evict)

//若存在相同的key,直接覆蓋

if (e.hash == hash &&

((k = e.key) == key || (key != null && key.equals(k))))

break;

p = e;}}

v oldvalue = e.value;

//若onlyifabsent為true,當key存在時,不覆蓋舊值

if (!onlyifabsent || oldvalue == null)

e.value = value;

afternodeaccess(e);

return oldvalue;}}

++modcount;

if (++size > threshold)

resize();

afternodeinsertion(evict);

return

null;

}

get方法

public v get(object key)
final nodegetnode(int hash, object key)  while ((e = e.next) != null);}}

return

null;

}

resize擴容方法

final node resize() 

else

if ((newcap = oldcap << 1) < maximum_capacity &&

oldcap >= default_initial_capacity)

//將容量擴充至以前的兩倍

newthr = oldthr << 1; // double threshold

}else

if (oldthr > 0) // initial capacity was placed in threshold

newcap = oldthr;

else

if (newthr == 0)

threshold = newthr;

@suppresswarnings()

node newtab = (node)new node[newcap];

table = newtab;

if (oldtab != null)

else

} while ((e = next) != null);

if (lotail != null)

if (hitail != null) }}

}}return newtab;

}

UIApplication深入學習

新建乙個任意型別的ios應用工程,加入我們在class prefix輸入是tc,我們可以看到工程中生成乙個類 在main函式中,autoreleasepool 函式中 說明 當應用程式將要入非活動狀態執行,在此期間,應用程式不接收訊息或事件。比如來 了。說明 當應用程式入活動狀態執行,這個剛好跟上面...

深入學習CSS

什麼是css?在之前的這篇文章中已經介紹了初步的介紹,詳細請看 div加css進一步講解了css中的內容,先總結如下圖 其實在實際開發中,我們通常採用是外部樣式的匯入,這樣做的好處是對於很對有同樣設計樣式的頁面可以實現樣式的共享,這樣我們不僅僅可以節省了大量的時間,並且也方便我們可以靈活的呼叫的樣式...

block深入學習

block的宣告和使用看上一節就行了。本章主要講block內部的實現過程及原理。block的定義和函式指標非常相似 對比一下 block定義 void someblock 函式指標定義 void functionpionter void functionname 當然區別還是有的,block的返回型...