精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

HashMap底層實現原理

開發 前端
JDK1.8中,是通過hashCode()的高16位異或低16位實現的:(h=k.hashCode())^(h>>>16),主要是從速度,功效和質量來考慮的,減少系統的開銷,也不會造成因為高位沒有參與下標的計算,從而引起的碰撞。

HashMap采用Node<K,V> 數組來存儲key-value對,每一個鍵值對組成了一個Node實體,Node類實際上是一個單向的鏈表結 構,它具有Next指針,可以連接下一個Node實體。

HashMap在JDK1.8之前和之后的區別

JDK1.8 之前,數組 + 鏈表 存儲結構

缺點就是哈希函數很難使元素百分百的均勻分布,這會產生一種極端的可能,就是大量的元素存在一個桶里

JDK1.8 之后:數組 + 鏈表 + 紅黑樹

  1. 添加元素時:鏈表長度 大于8的時候,轉換為紅黑樹
  2. 刪除元素、擴容時,同上,數量大于8時,也是采用紅黑樹形式存儲,但是在數量較少時,即數量小于6時,會將紅黑樹轉換回鏈表
  3. 遍歷、查找時,使用紅黑樹,他的時間復雜度O(log n),便于性能的提高。

數據結構

存儲結構


static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;

Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}

public final K getKey(){ return key; }
public final V getValue(){ return value; }
public final String toString(){ return key + "=" + value; }

public final int hashCode(){
return Objects.hashCode(key) ^ Objects.hashCode(value);
}

public final V setValue(V newValue){
V oldValue = value;
value = newValue;
return oldValue;
}

public final boolean equals(Object o){
if (o == this)
return true;
if (o instanceof Map.Entry) {
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
if (Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue()))
return true;
}
return false;
}
}


// Node<K,V> 數組 
transient Node<K,V>[] table;

//加載因子
final float loadFactor;

//默認加載因子 ,容量達到這個比例時自動擴容
static final float DEFAULT_LOAD_FACTOR = 0.75f;

// 數量大于8時,鏈表轉換為紅黑樹形式存儲
static final int TREEIFY_THRESHOLD = 8;

//即數量小于6時,會將紅黑樹轉換回鏈表,刪除元素時remove
static final int UNTREEIFY_THRESHOLD = 6;
//PUT 時每次都做hash
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
//put 函數核心算法
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null) // 這里的n 表示數組的長度。
// hash
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e); // 空實現
return oldValue;
}
}
++modCount; // modCount 是java集合中Fail-Fast的底層實現原理
if (++size > threshold) //擴容
resize();
afterNodeInsertion(evict);// 空實現
return null;
}

// Callbacks to allow LinkedHashMap post-actions
void afterNodeAccess(Node<K,V> p) { }
void afterNodeInsertion(boolean evict) { }
void afterNodeRemoval(Node<K,V> p) { }

思考

java集合中的快速失敗:modCount

//?快速失敗是Java集合的一種錯誤檢測機制,當多個線程對集合進行結構上的改變的操作時,有可能會產生fail-fast。

//舉個例子:假設存在兩個線程(線程1、線程2),線程1通過Iterator在遍歷集合A中的元素,在某個時候線程2修改了集合A的結構(是結構上面的修改,而不是簡單的修改集合元素的內容),那么這個時候程序就可能會拋出
ConcurrentModificationException異常,從而產生fast-fail快速失敗。

HashMap中遍歷算法如下:

final class KeySet extends AbstractSet<K> {
public final int size(){ return size; }
public final void clear(){ HashMap.this.clear(); }
public final Iterator<K> iterator(){ return new KeyIterator(); }
public final boolean contains(Object o){ return containsKey(o); }
public final boolean remove(Object key){
return removeNode(hash(key), key, null, false, true) != null;
}
public final Spliterator<K> spliterator(){
return new KeySpliterator<>(HashMap.this, 0, -1, 0, 0);
}
public final void forEach(Consumer<? super K> action){
Node<K,V>[] tab;
if (action == null)
throw new NullPointerException();
if (size > 0 && (tab = table) != null) {
int mc = modCount;
for (int i = 0; i < tab.length; ++i) {
for (Node<K,V> e = tab[i]; e != null; e = e.next)
action.accept(e.key);
}
if (modCount != mc)
//拋出異常,Fail-Fast
throw new ConcurrentModificationException();
}
}
}

優化hash 算法

JDK1.8中,是通過hashCode()的高16位異或低16位實現的:(h=k.hashCode())^(h>>>16),主要是從速度,功效和質量來考慮的,減少系統的開銷,也不會造成因為高位沒有參與下標的計算,從而引起的碰撞。

//擾動函數:促使元素位置分布均勻,減少碰撞幾率
static final int hash(Object key){
int h;
// 如果key == null 返回的值是 0
// 如果key !=null
// 首先計算 key 的 hashcode 值賦值給 h ,
// 然后與h 無符號右移16位后的二進制按位異或預算得到最后hash值
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

hash具體實現過程如下圖所示:

hash 計算過程與putval函數的應用

  1. key.hashCode();返回散列值也就是hashcode,假設隨便生成的一個值。
  2. n表示數組初始化的長度是16。
  3. &(按位與運算):運算規則:相同的二進制數位上,都是1的時候,結果為1,否則為零。
  4. ^(按位異或運算):運算規則:相同的二進制數位上,數字相同,結果為0,不同為1。

高16bit不變,低16bit和高16bit做了一個異或(得到的hashCode轉化為32位二進制,前16位和后16位低16bit和高16bit做了一個異或)

為什么這樣實現呢?

如果當n即數組長度很小,假設是16的話,那么n - 1即為1111 ,這樣的值和hashCode直接做按位與操作,實際上只使用了哈希值的后4位。如果當哈希值的高位變化很大,低位變化很小,這樣就很容易造成哈希沖突了,所以這里把高低位都利用起來,從而解決了這個問題。降低了Hash沖突的概率

為什么要用異或運算符

保證了對象的hashCode的32位值只要有一位發生改變,整個hash()返回值就會改變。盡可能的減少碰撞。

工作原理

存儲對象時,將K/V鍵值傳給put()方法:

  1. 調用hash(K)方法計算K的hash值,然后結合數組長度,計算得數組下標;
  2. 調整數組大小(當容器中的元素個數大于capacity*loadfactor時,容器會進行擴容resize為2n);
  3. hash碰撞

i.如果K的hash值在HashMap中不存在,則執行插入,若存在,則發生碰撞;

ii.如果K的hash值在HashMap中存在,且它們兩者equals返回true,則更新鍵值對;

iii.如果K的hash值在HashMap中存在,且它們兩者equals返回false,則插入鏈表的尾部(尾插法)或者紅黑樹中(樹的添加方式)。(JDK1.7之前使用頭插法、JDK1.8使用尾插法)

//get 實現
public V get(Object key) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}

/**
* Implements Map.get and related methods
*
* @param hash hash for key
* @param key the key
* @return
final Node<K,V> getNode(int hash, Object key) {
Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
if ((tab = table) != null && (n = tab.length) > 0 &&
(first = tab[(n - 1) & hash]) != null) {
if (first.hash == hash && // always check first node
((k = first.key) == key || (key != null && key.equals(k))))
return first;
if ((e = first.next) != null) {
if (first instanceof TreeNode)
return ((TreeNode<K,V>)first).getTreeNode(hash, key);
do {
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
} while ((e = e.next) != null);
}
}
return null;
}

問題思考?

Q:默認初始化大小是多少?為啥是這么多?為啥大小都是2的冪?

A:hash運算的過程其實就是對目標元素的Key進行hashcode,再對Map的容量進行取模,而JDK 的工程師為了提升取模的效率,使用位運算代替了取模運算,這就要求Map的容量一定得是2的冪。HashMap的容量為什么是2的n次冪,和這個putval方法中(n - 1) & hash的計算方法有著千絲萬縷的關系,符號&是按位與的計算,這是位運算,計算機能直接運算,特別高效,按位與&的計算方法是,只有當對應位置的數據都為1時,運算結果也為1,當HashMap的容量是2的n次冪時,(n-1)的2進制也就是1111111***111這樣形式的,這樣與添加元素的hash值進行位運算時,能夠(充分的散列),使得添加的元素均勻分布在HashMap的每個位置上,減少hash碰撞。

Q:HashMap如何有效減少碰撞?

A: 擾動函數:促使元素位置分布均勻,減少碰撞幾率 、使用final對象,并采用合適的equals()和hashCode()方法

責任編輯:武曉燕 來源: 今日頭條
相關推薦

2023-07-11 08:00:00

2023-10-18 10:55:55

HashMap

2021-08-29 07:41:48

數據HashMap底層

2022-12-19 08:00:00

SpringBootWeb開發

2021-01-08 08:34:09

Synchronize線程開發技術

2013-06-06 13:10:44

HashMap無鎖

2021-07-12 05:58:58

JavaHashMapJava 技術

2023-07-17 08:02:44

ZuulIO反應式

2022-12-26 09:27:48

Java底層monitor

2017-10-23 10:13:18

IO底層虛擬

2020-05-27 12:45:52

HashMapJava加載因子

2024-02-29 16:49:20

volatileJava并發編程

2025-03-27 04:00:00

2024-08-29 16:30:27

2021-12-13 10:43:45

HashMapJava集合容器

2017-03-22 14:23:58

Java HashMa實現原理

2024-03-14 14:56:22

反射Java數據庫連接

2024-01-29 08:00:00

架構微服務開發

2024-01-05 09:00:00

SpringMVC軟件

2020-11-05 11:14:29

Docker底層原理
點贊
收藏

51CTO技術棧公眾號

成人无码精品1区2区3区免费看| 日日橹狠狠爱欧美超碰| 国产精品主播一区二区| 国内精品嫩模av私拍在线观看| 亚洲成人1234| 9久久婷婷国产综合精品性色| 精品自拍一区| 91视频国产资源| 成人亚洲激情网| 六月丁香在线视频| 婷婷六月综合| 亚洲色在线视频| 成人免费播放视频| se01亚洲视频| 亚洲一区二区视频| 亚洲精品成人三区| 天堂在线中文网| 国产一区视频网站| 日本老师69xxx| 九九久久免费视频| 日韩精品久久| 亚洲欧美日韩中文视频| 制服.丝袜.亚洲.中文.综合懂| 日韩毛片免费观看| 亚洲国产精品久久一线不卡| 亚洲啪啪av| 日本天堂影院在线视频| 国产精品2024| 国产日韩欧美在线播放| 4438国产精品一区二区| 伊人久久成人| 久久亚洲精品一区| 亚洲图片另类小说| 精品久久97| 精品福利在线导航| 欧美高清精品一区二区| 国产第一精品| 91国产福利在线| 久久无码高潮喷水| 国产精品25p| 亚洲亚洲人成综合网络| 好吊色视频988gao在线观看| 在线毛片网站| 日本一区二区三区久久久久久久久不| 精品欧美一区二区在线观看视频| 成人无码一区二区三区| 国产东北露脸精品视频| 亚洲一区二区三区久久| aa视频在线免费观看| 久久99精品国产.久久久久久| 国产精品嫩草视频| 人人妻人人爽人人澡人人精品| 亚洲一区欧美二区| 欧美诱惑福利视频| 亚洲日本视频在线观看| 麻豆久久婷婷| 国产成人精品免高潮在线观看 | wwwwwxxxx日本| 欧美影视资讯| 欧美日韩精品一区二区三区蜜桃 | 日韩精品一区二区三| 亚洲大黄网站| 91地址最新发布| 亚洲午夜18毛片在线看| 先锋影音久久久| 国产成人午夜视频网址| 中文在线字幕免费观| 蜜臀精品久久久久久蜜臀| 国产综合视频在线观看| 国产三区在线播放| 高清不卡一区二区| 国产伦理一区二区三区| 欧美日韩国产综合视频 | 三区精品视频观看| 91精彩视频在线观看| 亚洲精品自拍动漫在线| 国产传媒久久久| 深夜成人在线| 欧美日本一区二区三区| 黑人巨大猛交丰满少妇| 超碰97久久| 亚洲日韩中文字幕| 网站永久看片免费| 国产精品mm| 日本一区二区三区在线播放| 中文字幕男人天堂| 国产精品夜夜爽| 久久精品成人一区二区三区蜜臀| 黄色小视频在线免费观看| 欧美激情一二三区| 国产精品av免费观看| 免费v片在线观看| 欧美日韩国产经典色站一区二区三区 | 精品免费日产一区一区三区免费| 国产视频精品久久| 一区二区三区在线播放| 黄色a级片免费| av国产精品| 日韩精品视频免费| 91高清免费观看| 国产精品综合| 96国产粉嫩美女| 黄色免费在线播放| 亚洲一区在线观看免费| 久草福利视频在线| 91国内精品| 日韩在线视频网站| 四虎成人在线观看| 国产91在线观看丝袜| 色一情一乱一伦一区二区三欧美| 色呦呦呦在线观看| 欧美日韩精品一区二区天天拍小说| 久久久久无码国产精品一区李宗瑞| 精品国产91| 91国产视频在线| 国产福利资源在线| 国产精品久久久久婷婷二区次| 国产九九九九九| 日韩成人视屏| 日韩在线视频播放| 国产精品传媒在线观看| 9久草视频在线视频精品| 日韩 欧美 自拍| 国产精品伦一区二区| 精品在线小视频| 久草资源在线视频| 激情综合色播五月| 日本一区视频在线观看| 爱啪啪综合导航| 精品国产免费人成电影在线观看四季| 色婷婷粉嫩av| 美国三级日本三级久久99| 欧美日韩精品免费在线观看视频| 波多野结衣中文在线| 日韩午夜在线观看视频| 亚洲最大的黄色网址| 久久电影网电视剧免费观看| 欧洲亚洲一区| 国产综合色区在线观看| 亚洲精品一区中文| 国产成人一级片| 97se亚洲国产综合自在线| 99er在线视频| 成人福利一区| 午夜精品久久久久久久白皮肤| a级片在线视频| 亚洲精品一二三四区| 黄色片免费网址| 你懂的成人av| www日韩av| 91破解版在线观看| 亚洲精品国产精品久久清纯直播| 日韩特黄一级片| 91原创在线视频| 免费黄色特级片| av在线不卡免费观看| 国产欧美日韩免费| 麻豆网在线观看| 欧美一区二区大片| 精品少妇爆乳无码av无码专区| 成人手机在线视频| 日本日本19xxxⅹhd乱影响| 日韩欧美在线精品| 国产精品久久91| 国产黄色小视频在线| 精品国产三级电影在线观看| 男人的天堂一区二区| 久久精子c满五个校花| 一区二区三区 欧美| 午夜影院欧美| 国产视频在线观看一区| 中文字幕不卡三区视频| 中文字幕av一区二区三区谷原希美 | 欧美videos极品另类| 日韩一区二区三区免费观看| 国产五月天婷婷| 久久久影院官网| 亚洲久久中文字幕| 欧美jizzhd精品欧美巨大免费| 国产精品久久国产精品| 久久久久久久| 美女福利视频一区| 青青国产在线| 欧美三级在线视频| 18精品爽视频在线观看| 国产日韩精品久久久| 亚洲一区二区图片| 国产免费成人| 综合国产精品久久久| 超碰在线成人| 国产精品视频在线观看| 91桃色在线| yw.139尤物在线精品视频| 丰满肉嫩西川结衣av| 欧美午夜视频网站| www.youjizz.com亚洲| 日本一区二区三区国色天香 | 欧美美乳视频| 99视频网站| 黄色欧美视频| 欧美一乱一性一交一视频| 欧美激情二区| 国产亚洲一级高清| 日本黄色不卡视频| 91.麻豆视频| www.日韩一区| 精品美女国产在线| 天天色影综合网| 久久日韩精品一区二区五区| 香蕉视频1024| 久久99国产乱子伦精品免费| 国产福利视频在线播放| 国产精品红桃| 成人在线免费观看网址| 第九色区aⅴ天堂久久香| 精品午夜一区二区三区| 欧美日本三级| 成人网在线视频| a成人v在线| 日韩av免费一区| 精精国产xxxx视频在线野外| 欧美另类极品videosbestfree| 国产片在线观看| 精品无人区乱码1区2区3区在线| www黄色在线观看| 欧美区视频在线观看| 潘金莲一级淫片aaaaaa播放| 五月婷婷激情综合| 久草视频在线资源站| 亚洲精品欧美二区三区中文字幕| 日韩精品卡通动漫网站| 成人av电影免费在线播放| 在线成人免费av| 国产麻豆日韩欧美久久| www.51色.com| 国产一区二三区| 欧美视频亚洲图片| 国内精品伊人久久久久av影院| 成人性做爰aaa片免费看不忠| 国产日韩一区二区三区在线播放 | 136福利第一导航国产在线| 久久国产色av| 69成人在线| 九色精品免费永久在线| 欧美日韩色网| 久久久久亚洲精品成人网小说| 在线看一级片| 欧美日韩国产第一页| 国产在线xxx| 97超碰蝌蚪网人人做人人爽| 欧美亚洲日本精品| 日韩免费观看在线观看| 97成人超碰| 成人激情视频免费在线| 精品视频在线播放一区二区三区| 91精品网站| 91夜夜蜜桃臀一区二区三区| 国产一区精品在线| 亚洲制服欧美另类| 色姑娘综合网| 欧美国产偷国产精品三区| 伊人久久大香线蕉av一区| 午夜激情久久| 国产va亚洲va在线va| 国产日韩欧美三级| 亚洲欧美另类动漫| 黄色日韩网站视频| 亚洲一区二区三区四区av| caoporn国产一区二区| 国产免费看av| 亚洲天堂网中文字| 日韩精品国产一区二区| 色婷婷久久久亚洲一区二区三区| 中文字幕一区二区人妻| 日韩一级大片在线| 三级在线播放| 久久久精品日本| 9999精品成人免费毛片在线看| 国产91精品久久久久| 免费视频观看成人| 国产经典一区二区三区| 久久综合欧美| 菠萝蜜视频在线观看入口| 99精品免费视频| www.国产福利| 久久视频一区二区| 天天看片中文字幕| 一本久道中文字幕精品亚洲嫩 | 国产伦精品一区二区三区在线观看 | 影音成人av| 97超碰人人模人人爽人人看| 卡通动漫精品一区二区三区| 亚洲狠狠婷婷综合久久久| 欧美天天在线| 天堂视频免费看| 91亚洲男人天堂| 亚洲最大的黄色网址| 色综合欧美在线| 亚洲精品网站在线| 尤物tv国产一区| a天堂资源在线| 91精品免费看| 国产成人精品999在线观看| 国产精品无码免费专区午夜| 美美哒免费高清在线观看视频一区二区 | 国产亚洲aⅴaaaaaa毛片| 伦理av在线| 成人深夜直播免费观看| 亚洲丁香日韩| 少妇大叫太大太粗太爽了a片小说| 日韩高清一级片| 538国产视频| 亚洲午夜久久久久久久久电影院| 在线观看毛片视频| 亚洲欧美国产精品| 超碰在线99| 国产 高清 精品 在线 a| 99久久99久久精品国产片桃花| www.亚洲天堂网| 不卡的电视剧免费网站有什么| 国产91在线播放九色| 91电影在线观看| 色综合久久网女同蕾丝边| 欧美激情视频给我| 日韩精品一区二区三区中文字幕| 亚洲午夜精品国产| 久久亚洲国产精品一区二区| 香蕉视频污视频| 一区二区高清在线| 国产免费黄色大片| 久久精品国产清自在天天线 | 97caopor国产在线视频| 国产日产欧美a一级在线| 成人同人动漫免费观看| 男人操女人免费| 久久精品一区二区三区av| 亚洲黄色一区二区| 日韩成人在线视频网站| 国产精品蜜芽在线观看| 国产在线一区二区三区四区| 亚洲久色影视| 网站免费在线观看| 欧美性xxxx极品hd欧美风情| 亚洲色图欧美视频| 91sa在线看| 一区二区三区四区在线看| 国产a级一级片| 久久精品一二三| 中文字幕 自拍偷拍| 久久深夜福利免费观看| 精品国产一区二| 18黄暴禁片在线观看| 成人晚上爱看视频| 国产成人精品片| 亚洲人成网站777色婷婷| 久久久成人av毛片免费观看| 亚洲欧洲久久| 国产成人综合在线播放| 国产在线观看你懂的| 亚洲国产欧美一区| 美女福利一区二区三区| 天堂一区二区三区| 国产最新精品精品你懂的| 深夜福利影院在线观看| 亚洲大胆人体av| 日韩欧美少妇| av电影一区二区三区| 丁香婷婷综合色啪| 丰满人妻老熟妇伦人精品| 日韩在线观看免费全集电视剧网站| 国产一区二区三区亚洲综合| 欧美黄色免费网址| 久久奇米777| 国产美女免费看| 韩国三级电影久久久久久| 九九久久成人| 91性高潮久久久久久久| 亚洲va天堂va国产va久| 欧美挠脚心网站| 国产中文欧美精品| 亚洲精品乱码久久久久久蜜桃麻豆| 91视频免费观看网站| 91精品国产全国免费观看| 国产黄色大片在线观看| 日本一区二区三区视频在线播放| 久草在线在线精品观看| 国产精品成人久久| 自拍视频国产精品| 加勒比色老久久爱综合网| 欧美成年人视频在线观看| 亚洲国产精品久久久久婷婷884 | 一级日本不卡的影视| 免费在线黄色影片| 亚洲一区二区三区在线免费观看| 国产精品婷婷| 黄色片子在线观看| 亚洲女人被黑人巨大进入al| 欧美h版在线观看| 91香蕉视频污版| 精品国产成人在线|