一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - Java中map內(nèi)部存儲方式解析

Java中map內(nèi)部存儲方式解析

2021-01-14 15:53清空萬里111 Java教程

這篇文章主要介紹了Java中map內(nèi)部存儲方式解析的相關(guān)內(nèi)容,涉及其實現(xiàn)方式,以及對存儲方式作了簡單的比較,具有一定參考價值,需要的朋友可了解下。

Map,即映射,也稱為 鍵值對,有一個 Key, 一個 Value 。

比如 Groovy 語言中,  def  map = ['name' : 'liudehua', 'age' : 50 ] ,則 map[ 'name' ]  的值是 'liudehua'。
那么 Map 內(nèi)部存儲是怎么實現(xiàn)的呢?   下面慢慢講解.

一、 使用 拉鏈?zhǔn)酱鎯?/strong>

這個以 Java 中的 HashMap 為例進(jìn)行講解。   HashMap 的內(nèi)部有個數(shù)組 Entry[]  table, 這個數(shù)組就是存放數(shù)據(jù)的。

Entry 類的定義大致是 :

?
1
2
3
4
5
class Entry {
Object key
Object value
Entry next;
}

所以, Entry[]  table  的每個元素都是一個鏈表,即 HashMap 的內(nèi)部存儲是 數(shù)組 + 鏈表,即拉鏈?zhǔn)酱鎯Α?/p>

當(dāng)往 HaspMap 中 put(key,  value) 數(shù)據(jù)時,先進(jìn)行  key.hashCode()  &  (table.length() - 1) ,得到一個小于 table.length() 的值, 稱為 index, 則這個新的 Entry 就屬于 table[index] 這個鏈表了 ( 如果鏈表還不存在,則把這個新的 Entry 作為鏈表的頭部了 );  然后開始從前往后遍歷  table[index] 這個鏈表,如果 key.equals( entry.key ), 那么表示這個 key 已經(jīng)有了舊值,則替換 value 的值即可;

否則,把這個新的 Entry 插入到 table[index] 鏈表的最前面.

以上就是 HashMap 的存儲方式介紹了, 而且可以知道,作為 HashMap 的 Key, 它的 hashCode() 和 equals() 方法都被使用了

二、數(shù)組存儲

1.分散的數(shù)組存儲

這個以 ThreadLocal  和 ThreadLocal.Values  類為例進(jìn)行講解。 Values 類里面有兩個變量, Object[]  table, 和 mask , table 就是存儲數(shù)據(jù)的數(shù)組了,table 的長度是 2 的倍數(shù) ,  mask 的值就是  table.length - 1 ;  這一點和 HashMap 的內(nèi)部存儲很像。  不過 table 中的每個元素就不是鏈表了。

當(dāng)往  Values 中進(jìn)行 put(key, value) 時,先進(jìn)行 key.hashCode & mask ,得到一個小于 table.length 的值,稱為 index (與上面的 HashMap 好像,哈哈), 然后去檢查 table[index] 的值,如果不存在,則在 table[index] 處放入 key, table[index + 1] 處放入 value; 如果已經(jīng)存在了,且 key.equals( oldKey ) 不成立,即發(fā)生了沖突,那么 index = index + 2 ( 此處是 + 2,因為 key ,value 兩個是挨著放的,一個元素占倆坑 ) ; 往下一地方找找,如果再沖突,再找,直到找到一個可插入的地方,把 table[index] = key, table[index + 1] = value; 

有兩處需要注意:

key.hashCode() 必須是 2 的倍數(shù), 否則 index 的值有可能為奇數(shù),如此就可能發(fā)生沖突了.  可參考 ThreadLocal.hash 這個成員變量

table 內(nèi)部的數(shù)據(jù)是分散著存儲的.

2.連續(xù)的數(shù)組存儲

這個以 Android 中新增的 ArrayMap 為例進(jìn)行分析( 據(jù)說沒 ArrayMap 是用來替換 HashMap 的哈 ),  ArrayMap 中有兩個主要變量, int[]  mHashes, Object[]  mArrays.

mHashes 主要是存放 key 的 hash 值的, mArrays 是用來存放數(shù)據(jù)的,它也是奇數(shù)存放 key ,偶數(shù)存放 value , key 和 value 順序排列( 這個和 TheadLocal.value 中的 table 存儲方式很像 )。  mArrays 的長度是 mHashes 的 2 倍,畢竟 mArrays 是 key, value 都要存嘛~

mHashes 中存放 key 的 hash 值,是從小到大排列的,如果有多個 key 的 hash 值有一樣的,那么就挨著排列

當(dāng)往 ArrayMap 中進(jìn)行 put(key, value) 時,先 int hash = key.hashCode, 然后通過二分查找在 mHashes 中查找 hash 的位置( 如果里面有,就返回,如果無,就先找到最接近的位置,然后進(jìn)行取反操作并返回 )  index,如果 index > 0 ,那么再去 mArrays 中 2 * index 處獲取 key 值,比對兩個 key 是否 equals(), 如果不相等,那么再分別向上、向下查找附近相同 hash 值的 key ,看是否有 equals() 的 key, 若有,則替換,若無,則插入;    如果 index < 0 ,表示之前沒有相等 hash 的 key 插入過,那么 index = ~index( 再次取反,就是個正數(shù)了,代辦要插入的位置), 再在 mHashes 的 index 處插入 hash, 在 mArrays 的 2 * index 處插入 key, 在 (2 * index ) + 1 處,插入 value .

注意:

mHashes 和 mArrays 在插入新數(shù)據(jù)時,都需要把插入位置后面的數(shù)據(jù)向后移動一個單位,這個對于頻繁插入、刪除的動作來說消耗比較大.

key 的 hash 大小決定了插入的順序

3.以數(shù)字為 key 的數(shù)組存儲

這類的 map 比較特殊,key 是數(shù)字類型。  這個以 Android 中新增的 SparseArray 進(jìn)行分析。 SparseArray 中有兩個主要變量, int[]  mKeys  和  Object[]  mValues , mKeys 是存放 key 的,是個有序數(shù)組,從小到大排列;  mValues 是與 mKeys 一一對應(yīng)的 value 值集合.   mKeys 和 mValues 的長度是相等的。

當(dāng)往  SparseArray 中 put(key, value) 時,先用二分查找在 mKeys 中查找 key 所在的位置 (如果找到,返回; 如果沒有找到,則找到它應(yīng)該插入的位置,取反并返回) ,記為 index, index > 0 ,則直接在 mValues[index] 處替換 value; 如果 index < 0 ,則 index = ~index, 即取反, 然后在 mKeys 的 index 處插入 key , 在 mValues[index] 處插入 value ,之前的數(shù)據(jù)自 index 處后移一個單位。

注意:

mKeys 和 mArrays 的數(shù)據(jù)插入時,都是要進(jìn)行數(shù)據(jù)移動的,對頻繁插入、刪除的 map 來說消耗很大.
最后了,對它們的優(yōu)缺點做些對比。

HashMap : 內(nèi)存占用較大,增、刪的效率較高,改、查的效率一般

ThreadLocal.Values :  內(nèi)存占用一般,當(dāng)數(shù)據(jù)量比較小時,增刪改查的效率高;數(shù)據(jù)量大時,增刪改查效率一般

ArrayMap: 內(nèi)存占用較小,改、查的效率高,增、刪的效率較低

SparseArray : 內(nèi)存占用較小,改、查的效率高,增、刪的效率低,且主鍵是數(shù)字

總結(jié)

我們不評判哪種存儲方式好,一切都要以實際情況實際分析,找出最符合的那種存儲,哈哈~。希望對大家有所幫助。感謝大家對本站的支持。

原文鏈接:http://blog.csdn.net/weixinzhang/article/details/50614438

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚洲码在线观看 | 舔穴吸奶| 香港三级浴室女警官 | 欧美xingai | 奇米色7777 | 出水小说 | 白丝萝莉喷水 | 国产在线一区二区杨幂 | 日韩高清成人毛片不卡 | 99pao在线视频精品免费 | 啊哈~嗯哼~用力cao我小说 | 97影院秋霞国产精品 | 国产日韩一区二区三区在线播放 | 日韩成人一级 | 久久国产综合精品欧美 | 含羞草传媒一天免费看下 | 日韩中文在线 | 91普通话国产对白在线 | 激情婷婷成人亚洲综合 | 亚洲欧美日韩中文高清一 | 1986葫芦兄弟全集免费观看第十集 | 天天做日日做天天添天天欢公交车 | 91国语自产拍在线观看 | 污樱桃视频 | 成人在线免费看 | 被夫上司侵犯了中文字幕 | babes性欧美30 | 久久伊人免费 | 日本mv精品中文字幕 | 99在线观看免费视频 | 91porn在线观看国产 | 日本高清免费中文字幕不卡 | 青春草视频在线免费观看 | 嫩草研究 | 免费观看俄罗斯特黄特色 | 91精品手机国产露脸 | 清纯漂亮女友初尝性过程 | 欧美一卡二卡科技有限公司 | 欧美 亚洲 综合 卡通 另类 区 | 亚洲国产精品久久网午夜 | 波多野结在线观看 |