日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

浅谈关于Java中map这个类衍生的类

發(fā)布時間:2023/12/31 java 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浅谈关于Java中map这个类衍生的类 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

最近又研究了一下關(guān)于map衍生的類,hashMap LinkedHashMap?TreeMap?hashTable?ConcurrentHashMap,沒有對代碼的粘貼,純粹用文字根據(jù)自己的理解看了一遍,以此簡單的整理。

/**
*定義:Map java中的一種數(shù)據(jù)存儲結(jié)構(gòu),它的存儲類型是key,val形式的,key,val都可以為空,但只保存一份,key的存儲是基于鍵的hash
*值進(jìn)行一些運(yùn)算得到物理存儲的地址。
*對于Map的實(shí)現(xiàn)類,我們著重講一下HashMap Hashtable ConcurrentHashMap
*HashMap: 內(nèi)部數(shù)據(jù)存儲的方式是基于數(shù)組和鏈表的形式進(jìn)行存儲的。數(shù)組的下標(biāo)就是根據(jù)key的hashCode值進(jìn)行運(yùn)算的出來的。下面我們看下
*它是如何計算的:(h = key.hashCode()) ^ (h >>> 16) 這個是計算hash的值防止hash的一個沖突(^相同為0,不同為1)
*計算下標(biāo):(n - 1) & hash ( &全1為1 其他為0 ) 計算下標(biāo)值,其下標(biāo)值不會超過map自定義的下標(biāo)值
*計算完下標(biāo)的值以后,接下來就是解決hash沖突,和值得替換。
*如果映射到的下標(biāo)上面值為空,直接創(chuàng)建一個新的節(jié)點(diǎn)放到對應(yīng)的
*下標(biāo)下面就可以了。數(shù)組放的對象Node是實(shí)現(xiàn)Map內(nèi)部的Entry接口,儲存的值有hash,鍵,值,鏈表的下一個元素。
*如果不為空,判斷hash值和值是否與此下標(biāo)下的值相等,如果相等就覆蓋,不等遍歷鏈表上的值進(jìn)行比較。
*首先:這里需要注意的是binCount 這個值是判斷在解決沖突的使用鏈表還是用紅黑樹
*第二:在遍歷的時候,其實(shí)很簡單的就是有一個無限的for循環(huán),然后就是修改e的值,以及鏈表轉(zhuǎn)樹的過程。
*接下來你會發(fā)現(xiàn)兩個方法:afterNodeAccess? afterNodeInsertion,這兩個是用于排序的,但是hashmap并沒有實(shí)現(xiàn),所以是無須的,
*而LinkedHashMap實(shí)現(xiàn)了這兩個方法,所以LinkedHashMap是有序的。
*最后最重要的就是一個擴(kuò)容機(jī)制,注意兩點(diǎn)吧:
*第一:擴(kuò)容后的大小為多少,一般是原來的2倍,其他情況下可能是是integer的最大值
*第二:在擴(kuò)容的時候,(e.hash & oldCap) == 0 這個我也不明白
基本上插入就說完了。
下面是取數(shù):
*取數(shù)據(jù)就很簡單了,首先根據(jù)hash找到對應(yīng)數(shù)據(jù)的下標(biāo),再分三種情況去找到對應(yīng)的數(shù)據(jù)。
其實(shí)在hashMap中有幾個關(guān)鍵值需要掌握以下:
*DEFAULT_INITIAL_CAPACITY 默認(rèn)容量大小
*MAXIMUM_CAPACITY 最大的容量
*DEFAULT_LOAD_FACTOR 擴(kuò)張因子,用于判斷當(dāng)前的容量是否需要擴(kuò)容的一個因子
*threshold 擴(kuò)容標(biāo)識帶下,大于就擴(kuò)容
*TREEIFY_THRESHOLD 鏈表轉(zhuǎn)平衡二叉樹的標(biāo)識

**/


/**
LinkedHashMap 是一個有順序的map,本身繼承與HashMap 只是他實(shí)現(xiàn)了afterNodeAccess? afterNodeInsertion 這個兩個方法
所以他是一個有順序的map,而且里面維護(hù)的是一個雙端鏈表
*LinkedHashMap 里面的Entry 繼承制hashmap里的node
*對于插入的操作,本身用到得是父類的方法,只是實(shí)現(xiàn)了其中的兩個方法。
*afterNodeAccess:move node to last 訪問過就排到最后
*
*afterNodeInsertion:possibly remove eldest
*
*對于上面的兩部分的理解,其實(shí)拿出5分鐘畫個簡單的草圖就理解了。
*
除了LRU ,其他的功能和hashmap差不多。
**/


/**
? *treemap 一種可以自定義排序map,內(nèi)部引用Comparator實(shí)現(xiàn)排序。
? *默認(rèn)是根據(jù)鍵的compareTo 進(jìn)行排序的
? *可以在實(shí)例化treemap的時候 自己實(shí)現(xiàn)Comparator類,來實(shí)現(xiàn)自己定義的排序規(guī)則
? *?
?*/


/**
? *在研究hashMap的時候我們忘說了關(guān)于多線程的問題,其實(shí)? hashMap是線程不安全的,這樣我們來看下,為什么
? *Hashmap不是線程安全的。
? *首先線程的定義:當(dāng)在多線程的情況下,我們的數(shù)據(jù)不會因?yàn)榫€程切換而導(dǎo)致數(shù)據(jù)異常就是線程安全的。
? *而對于hashmap來說,它在多線程的情況下,在添加,刪除,查詢的時候回出現(xiàn)異常。
? *
? *
**/
/**
? *基于hashmap是線程不安全的,而我們現(xiàn)在都是多線程的環(huán)境下,jdk也有線程線程安全的類,hashtable,ConcurrentHashMap ?
? *對于hashtable來說,它在實(shí)現(xiàn)線程安全的時候是在所有線程不安全的方法上面添加synchronized關(guān)鍵字,而ConcurrentHashMap 1.8之前是針對于Segment
? *的分段鎖外,1.8之后是基于樂觀鎖的思想進(jìn)行的一個添加和獲取,是一個并發(fā)散列映射表的實(shí)現(xiàn),它允許完全并發(fā)的讀取,并且支持給定數(shù)量的并發(fā)更新,
? *加volatile來做線程安全的。但是在一定的程度上,ConcurrentHashMap 不能完全代替hashtable,雖然分段鎖的鎖粒度小,運(yùn)行的速度快,
? *但是它在極限的條件下會出現(xiàn)一個修改異常,但這個是很小概率發(fā)生的,所以我們在用的時候都不太會考慮這個問題。對于hashtable基本就是在
? *hashmap上面進(jìn)行添加synchronized關(guān)鍵字,沒什么好講的,接下來我們重點(diǎn)分析一下ConcurrentHashMap
? *
? *ConcurrentHashMap,從初始化,插入數(shù)據(jù),查詢數(shù)據(jù),刪除數(shù)據(jù)四個層面說
? *
? *初始化:初始化和hashmap基本一樣的
? *
? *put:在添加數(shù)據(jù)的時候,hash的值的計算是一樣的,首先獲取一下添加數(shù)據(jù)計算出來的位置上面是否有數(shù)據(jù),用到了,unsafe
? *安全類,在獲取到為空的情況下,會設(shè)置一個空值casTabAt(tab, i, null,new Node<K,V>(hash, key, value, null)),底層
? *的實(shí)現(xiàn)是U.compareAndSwapObject(tab, ((long)i << ASHIFT) + ABASE, c, v)
? *如果當(dāng)前的值得hash為-1就 如果調(diào)整了大小,可以幫助轉(zhuǎn)移。基本在添加的時候也是基平衡樹。
? *插入是并發(fā)式的,鎖是基于synchronized 的做線程安全,其中優(yōu)化表大小,以及擴(kuò)容機(jī)制
? *
? *get:也是可以并發(fā)的讀,內(nèi)部的實(shí)現(xiàn)是通過unfade的getObjectVolatile根據(jù)內(nèi)存地址進(jìn)行獲取,保證了除table是Volatile
? *下而內(nèi)部對象不是Volatile會出現(xiàn)數(shù)據(jù)異常的情況
? *
? *
?**/

總結(jié)

以上是生活随笔為你收集整理的浅谈关于Java中map这个类衍生的类的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。