最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入理解HashMap各個(gè)方法的源碼

 更新時(shí)間:2023年12月02日 09:22:30   作者:nuomizhende45  
這篇文章主要介紹了深入理解HashMap各個(gè)方法的源碼,HashMap初始容量不能為負(fù)數(shù),若初始容量大于最大容量,則讓它等于最大容量,負(fù)載因子必須大于0,并且傳入的initialCapacity不是HashMap的容量大小,需要的朋友可以參考下

HashMap各個(gè)方法的源碼

put方法

首先分析第一個(gè)比較重要的方法 put 方法,源碼如下

public V put(K key, V value) {
if (key == null)
return putForNullKey(value);  //這里判斷key是否為空,若為空則調(diào)用putForNullKey處理null值
int hash = hash(key); //根據(jù)key的hashCode計(jì)算hash值
int i = indexFor(hash, table.length);//搜索該key的hash值在table中的索引,其中table是當(dāng)HashMap用于存放entry的一個(gè)數(shù)組
//這里循環(huán)遍歷table中對(duì)應(yīng)該索引的entry,若發(fā)現(xiàn)存在key與put進(jìn)來的key相同則覆蓋其value值
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
//將key value 添加到 索引i處
addEntry(hash, key, value, i);
return null;
}

分析上面的源碼,我們可以得到下面的結(jié)論:

當(dāng)我們?cè)噲D將一個(gè)key-value 調(diào)用put方法放入HashMap的時(shí)候,首先會(huì)調(diào)用key的hashCode方法算出該Entry存放的位置,若兩個(gè)key的hashCode相同則在table中的存儲(chǔ)位置相同,則先調(diào)用equals方法判斷兩個(gè)key是否相同,相同則覆蓋,不相同則產(chǎn)生一個(gè)Entry鏈表(因?yàn)閠able數(shù)組中一個(gè)索引位置只能放入一個(gè)Entry,所以當(dāng)有多個(gè)key的hashCode相同時(shí),這些key就會(huì)以鏈表的形式存在,并且最后put進(jìn)來的key在鏈表的最前面)

構(gòu)造方法

然后則是HashMap的構(gòu)造方法,這里以 HashMap(int initialCapacity, float loadFactor)這個(gè)構(gòu)造器為例,源碼如下

public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
// Find a power of 2 >= initialCapacity
int capacity = 1;
while (capacity < initialCapacity)
capacity <<= 1;
this.loadFactor = loadFactor;
threshold = (int)Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
table = new Entry[capacity];
useAltHashing = sun.misc.VM.isBooted() &&
(capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
init();
}

從上面的源碼可以看出 ,初始容量不能為負(fù)數(shù),若初始容量大于最大容量,則讓它等于最大容量,負(fù)載因子必須大于0,并且傳入的initialCapacity不是HashMap的容量大小,

實(shí)際容量大小的計(jì)算規(guī)則是大于傳入的initialCapacity的最小的2的n次方,比如傳入的initialCapacity是5 那么實(shí)際容量則是8 因?yàn)?的3次方大于5。

get方法

下面再分析一下HashMap的存儲(chǔ)性能,下面的 get方法的源碼

public V get(Object key) {
if (key == null)
return getForNullKey();
Entry<K,V> entry = getEntry(key);
return null == entry ? null : entry.getValue();
}
final Entry<K,V> getEntry(Object key) {
int hash = (key == null) ? 0 : hash(key);
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
}
return null;
}

再次強(qiáng)調(diào)一下table的概念,table就是當(dāng)我們初始化一個(gè)HashMap時(shí),會(huì)自動(dòng)創(chuàng)建一個(gè)長(zhǎng)度為capacity的Entry數(shù)組,我們把這個(gè)數(shù)組存放元素的位置叫“桶”,并且每個(gè)桶只存儲(chǔ)一個(gè)Entry元素(也就是我們的鍵值對(duì)),并且當(dāng)我們put一個(gè)鍵值對(duì)時(shí),先計(jì)算key的hashCode來判斷這個(gè)鍵值對(duì)會(huì)放入哪一個(gè)桶,所以若多個(gè)key的hashCode相同時(shí),他們都要被放入一個(gè)桶里面,但是一個(gè)桶里面只能放入一個(gè)Entry(鍵值對(duì)),要解決這個(gè)問題先看下面的代碼

Entry(int h, K k, V v, Entry<K,V> n) {
value = v;
next = n;
key = k;
hash = h;
}

這是Entry的構(gòu)造方法,我們可以看出Entry對(duì)象包含一個(gè)Entry的引用,用來指向下一個(gè)Entry,這樣就解決了hashCode相同,存放沖突的問題,所以當(dāng)有多個(gè)key的hashCode相同時(shí),就會(huì)形成一個(gè)Entry鏈,我們從get方法可以看出當(dāng)系統(tǒng)通過key的hashCode找到了對(duì)應(yīng)的桶的時(shí)候,會(huì)遍歷這個(gè)Entry鏈,來找到我們要取的value的key

這個(gè)時(shí)候,若剛好這個(gè)Entry在鏈表的末端(也就是我們最開始put進(jìn)去的Entry)那么當(dāng)這個(gè)鏈表太長(zhǎng)了,勢(shì)必會(huì)影響我們的查詢性能,這個(gè)時(shí)候就引出了loadFactor(負(fù)載因子的說法),HashMap的默認(rèn)附在因子是0.75

我對(duì)負(fù)載因子的理解就是,表示HashMap在什么時(shí)候擴(kuò)容,也就是說若我們初始的HashMap容量是16 負(fù)載因子是0.75

那么當(dāng)有12個(gè)“桶”有了Entry時(shí),HashMap就會(huì)擴(kuò)容,并且擴(kuò)大的容量是原來容量的2倍,為什么是12呢?因?yàn)?.75x16=12。

并且負(fù)載因子是可以更改的,修改它的前提是如果內(nèi)存比較緊張就可以適當(dāng)?shù)脑黾迂?fù)載因子

若空間,內(nèi)存比較充足,更關(guān)注查詢效率則減少負(fù)載因子。為什么會(huì)這樣呢?因?yàn)槿糌?fù)載因子減少了,比如說減少到了0.5,默認(rèn)HashMap容量大小還是16

那么當(dāng)我有8個(gè)"桶"中存放了Entry數(shù)組時(shí)我就會(huì)擴(kuò)容了,該桶里的Entry鏈相比于之前就不會(huì)那么長(zhǎng),從而提升了查詢性能。

到此這篇關(guān)于深入理解HashMap各個(gè)方法的源碼的文章就介紹到這了,更多相關(guān)HashMap方法的源碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解析Java的Jackson庫中對(duì)象的序列化與數(shù)據(jù)泛型綁定

    解析Java的Jackson庫中對(duì)象的序列化與數(shù)據(jù)泛型綁定

    這篇文章主要介紹了解析Java的Jackson庫中對(duì)象的序列化與數(shù)據(jù)泛型綁定,Jackson通常被用來實(shí)現(xiàn)Java對(duì)象和JSON數(shù)據(jù)的相互轉(zhuǎn)換功能,需要的朋友可以參考下
    2016-01-01
  • java中對(duì)象的強(qiáng)、軟、弱、虛四種引用詳解

    java中對(duì)象的強(qiáng)、軟、弱、虛四種引用詳解

    這篇文章主要介紹了java中對(duì)象的強(qiáng)、軟、弱、虛四種引用詳解,對(duì)象的引用分為4種,分別是強(qiáng)引用>軟引用>弱引用>虛引用,程序員可以通過不同的引用控制對(duì)象的生命周期,方便垃圾回收,使程序更加靈活的控制對(duì)象生命周期,需要的朋友可以參考下
    2023-09-09
  • Spring?Boot?基于?CAS?實(shí)現(xiàn)單點(diǎn)登錄的原理、實(shí)踐與優(yōu)化全解析(最新整理)

    Spring?Boot?基于?CAS?實(shí)現(xiàn)單點(diǎn)登錄的原理、實(shí)踐與優(yōu)化全解析(最新整理)

    本文詳解SpringBoot集成CAS單點(diǎn)登錄的原理、實(shí)現(xiàn)步驟及優(yōu)缺點(diǎn),涵蓋CASServer與Client架構(gòu)、票據(jù)機(jī)制、配置方法,并提供優(yōu)化策略如集群部署、緩存加速和用戶體驗(yàn)提升方案,助力企業(yè)實(shí)現(xiàn)統(tǒng)一認(rèn)證與高效管理,感興趣的朋友一起看看吧
    2025-07-07
  • Java并發(fā)編程之線程間的通信

    Java并發(fā)編程之線程間的通信

    當(dāng)線程在系統(tǒng)內(nèi)運(yùn)行時(shí),程序通常無法準(zhǔn)確的控制線程的輪換執(zhí)行,但我們可以通過一些機(jī)制來保障線程的協(xié)調(diào)運(yùn)行,本文著重講解線程間的通信機(jī)制
    2021-06-06
  • Spring Framework中JDBC批量操作的三種實(shí)現(xiàn)方式

    Spring Framework中JDBC批量操作的三種實(shí)現(xiàn)方式

    本文詳細(xì)介紹了如何使用 Spring 的 JdbcTemplate 進(jìn)行高效的數(shù)據(jù)庫批量更新,從而減少與數(shù)據(jù)庫之間的網(wǎng)絡(luò)往返次數(shù)(round-trips),提升性能,下面我將用通俗易懂的方式,結(jié)合代碼示例和實(shí)際場(chǎng)景給大家詳細(xì)說說,需要的朋友可以參考下
    2025-10-10
  • Java使用Soap方式調(diào)用WebService接口代碼示例

    Java使用Soap方式調(diào)用WebService接口代碼示例

    Java調(diào)用WebService接口是指通過Java語言來訪問并與WebService進(jìn)行交互,WebService是一種基于Web的服務(wù)架構(gòu),它通過標(biāo)準(zhǔn)的XML和HTTP協(xié)議來提供服務(wù),這篇文章主要給大家介紹了關(guān)于Java使用Soap方式調(diào)用WebService接口的相關(guān)資料,需要的朋友可以參考下
    2024-03-03
  • RocketMQ設(shè)計(jì)之同步刷盤

    RocketMQ設(shè)計(jì)之同步刷盤

    這篇文章主要介紹了RocketMQ設(shè)計(jì)之同步刷盤,文章主要通過CommitLog的handleDiskFlush方法展開全文內(nèi)容,實(shí)現(xiàn)同步刷盤,下面文章詳細(xì)介紹,需要的小伙伴可以參考一下
    2022-03-03
  • Spring Boot 直接用jar運(yùn)行項(xiàng)目的方法

    Spring Boot 直接用jar運(yùn)行項(xiàng)目的方法

    這篇文章主要介紹了Spring Boot 直接用jar運(yùn)行項(xiàng)目的方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下
    2018-02-02
  • Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(4)

    Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(4)

    下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧,希望可以幫到你
    2021-07-07
  • java引用類型WeakReference用法及原理詳解

    java引用類型WeakReference用法及原理詳解

    Java弱引用(WeakReference)是一種特殊的引用類型,當(dāng)垃圾回收器運(yùn)行時(shí),無論內(nèi)存是否充足,只要發(fā)現(xiàn)對(duì)象僅被弱引用指向,就會(huì)立即回收該對(duì)象,這篇文章主要介紹了java引用類型WeakReference用法及原理的相關(guān)資料,需要的朋友可以參考下
    2026-01-01

最新評(píng)論

北宁市| 桃源县| 都匀市| 奉新县| 犍为县| 苏尼特左旗| 英山县| 漳平市| 乌拉特中旗| 介休市| 泸西县| 龙陵县| 谷城县| 新和县| 绥芬河市| 闵行区| 通山县| 迁西县| 普陀区| 邓州市| 时尚| 南城县| 长武县| 永康市| 和硕县| 云梦县| 六盘水市| 嘉善县| 二连浩特市| 阿坝| 札达县| 鲁山县| 蒲江县| 荥经县| 麦盖提县| 三原县| 峨眉山市| 磐石市| 富裕县| 正安县| 宁阳县|