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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

linkhashmap原理_LinkedHashMap原理

發布時間:2023/12/19 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linkhashmap原理_LinkedHashMap原理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

LinkedHashMap和HashMap經常會一同問到,不過看了LinkedHashMap內部的源碼相對比較簡單,如果事先看過HashMap的源碼的話。

概覽

首先可以看到LinkedHashMap是繼承HashMap的,所有HashMap能干的事,LinkedHashMap也能干。

然后多個幾個屬性,解釋如下

public class LinkedHashMap

extends HashMap

implements Map{

/**

HashMap的節點增加before和after字段

*/

static class Entry extends HashMap.Node {

Entry before, after;

Entry(int hash, K key, V value, Node next) {

super(hash, key, value, next);

}

}

/**

* 雙向鏈表的頭結點

*/

transient LinkedHashMap.Entry head;

/**

* 雙向鏈表的尾節點

*/

transient LinkedHashMap.Entry tail;

/**

* 雙向鏈表的訪問順序,true的話房屋有序,false時插入有序。

*/

final boolean accessOrder;

...

}

從上面大概可以看出來LinkedHashMap是一個雙向鏈表加Map。在HashMap基礎上多個頭指針,尾指針,然后節點相互連接

image.png

get操作

看源碼

public V get(Object key) {

Node e;

//如果未獲取到元素,返回null

if ((e = getNode(hash(key), key)) == null)

return null;

//如果獲取到了元素,判斷accessOrder,如果為true代表按訪問排序。

if (accessOrder)

afterNodeAccess(e);

return e.value;

}

//把參數中的節點移動至鏈表的尾節點

void afterNodeAccess(Node e) {

LinkedHashMap.Entry last;

//last節點為尾節點

if (accessOrder && (last = tail) != e) {

//先得到e節點的前節點,后節點,與自身節點,

// 加上尾節點有四個節點了

LinkedHashMap.Entry p =

(LinkedHashMap.Entry)e, b = p.before, a = p.after;

//這幾個主要操作就是把節點移動至尾巴節點。

p.after = null;

if (b == null)

head = a;

else

b.after = a;

if (a != null)

a.before = b;

else

last = b;

if (last == null)

head = p;

else {

p.before = last;

last.after = p;

}

tail = p;

++modCount;

}

}

畫的比較丑,但是鏈表的刪除操作,大家懂的,O(1),改變一下前后節點的指針即可。

image.png

put操作

put操作,采用的仍然為HashMap原本的操作,不過擴展了節點插入之后操作的方法

put節點的時候,新的節點會維持一個鏈表。

//覆蓋了原本的newNode方法,沒一個新的節點都做一次鏈表的操作

Node newNode(int hash, K key, V value, Node e) {

LinkedHashMap.Entry p =

new LinkedHashMap.Entry(hash, key, value, e);

linkNodeLast(p);

return p;

}

// 把節點放到最后面

private void linkNodeLast(LinkedHashMap.Entry p) {

LinkedHashMap.Entry last = tail;

tail = p;

if (last == null)

head = p;

else {

p.before = last;

last.after = p;

}

}

//HashMap方法

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,

boolean evict) {

Node[] tab; Node p; int n, i;

if ((tab = table) == null || (n = tab.length) == 0)

n = (tab = resize()).length;

if ((p = tab[i = (n - 1) & hash]) == null)

tab[i] = newNode(hash, key, value, null);

else {

Node 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)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;

if (++size > threshold)

resize();

afterNodeInsertion(evict);

return null;

}

//重寫remoeEldestEntry可實現LRU算法

void afterNodeInsertion(boolean evict) { // possibly remove eldest

LinkedHashMap.Entry first;

if (evict && (first = head) != null && removeEldestEntry(first)) {

K key = first.key;

removeNode(hash(key), key, null, false, true);

}

}

resize方法

resize與HashMap沒有變化,這里溫故一下, 參考之前HashMap的resieze

擴容兩倍之后,會重新計算Hash。

假設原本容量為:

16 = 0x10000 ,那么16以下的數與16進行hash都得0. 16以上的數&16為正數

擴容之后,容量變為32,需要重新分配位置的為大于原本16的數,然后加上新的擴容量計算得新的位置。

32 = 0x100000

最后

Java基礎中的集合類,有必要掌握

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的linkhashmap原理_LinkedHashMap原理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。