日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

JAVA的那些数据结构实现总结,实现,扩容说明

發(fā)布時間:2025/5/22 25 如意码农
生活随笔 收集整理的這篇文章主要介紹了 JAVA的那些数据结构实现总结,实现,扩容说明 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

能沉淀下來的東西,往往都很基礎(chǔ),整理了下JAVA中遇到的數(shù)據(jù)結(jié)構(gòu)

目錄大綱:

到目前接觸到的

有幾個說明:

可擴容數(shù)組

ArrayList 擴容數(shù)組的實現(xiàn), 滿了后擴容,擴容在1.5倍,通過copy過來,無擴容因子

     int newCapacity = oldCapacity + (oldCapacity >> 1);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);

可擴容的數(shù)組鏈表

數(shù)組鏈表的擴容實現(xiàn):

以HashMap為例子, 當鏈表深度過長,或生產(chǎn)個新的數(shù)組鏈表進行copy

注意:

擴容過程中容易出現(xiàn)死鏈,下面是死鏈的個演示

擴容前
[ 1 ] [ 2 ] [ 3 ] [ 空]
  5     10

第一個線程擴容后,數(shù)組鏈表如下

[ 1 ] [ 10 ] [3] [] [] [] []
          2

第二個線程又把從頭把2指向10,然后2和10形成了個死循環(huán)

擴容代碼

//對HashMap死鏈理解的注解 . 2017.02.17 by 何錦彬 JDK,1.7.51

void transfer(Entry[] newTable, boolean rehash) {
//獲取新table的容量
int newCapacity = newTable.length;
//迭代以前的數(shù)組
for (Entry<K,V> e : table) {
//如果數(shù)組上有元素
while(null != e) {
// 賦值next
Entry<K,V> next = e.next;
//獲取e在新的table里的位置
if (rehash) {
e.hash = null == e.key ? 0 : hash(e.key);
}
int i = indexFor(e.hash, newCapacity);
//把e指向當前的新數(shù)組里的第一個元素,這里會并發(fā)了,如果在這斷點等待下個線程過來,就會死循環(huán),嘗試下
e.next = newTable[i];
//替代新數(shù)組的位置
newTable[i] = e;
e = next;
}
}
}

stack棧的實現(xiàn) ,基于數(shù)組繼承自Vector(故線程安全):

獲取peek():get(len-1)

出棧 pop(): 從數(shù)組最大坐標開始取出,peek(len-1) , 然后remove

入棧 push(o) : add(o)

阻塞隊列

阻塞隊列的實現(xiàn):

基于數(shù)組和單向鏈表

獲取:peek(),

實現(xiàn):重入鎖保證線程安全,peek(),從頂部獲取

阻塞入隊:put(o),

實現(xiàn): 重入鎖保證線程安全,通過Condition阻塞,無超時,支持Interrupt

帶超時阻塞入隊: offer(o,timeout, tmeUnit),

實現(xiàn): 重入鎖保證線程安全,通過Condition阻塞,condition方法,awaitNanos(納秒),支持Interrupt

其它注意點

當前數(shù)組的大小: AtomicInteger計算,用CAS保證同步,記得ReentrantLock必須是全局變量,局部的話,每次鎖的對象是this.

紅黑樹:

紅黑樹的實現(xiàn),TreeMap舉例,加入自己的注釋的理解

//對treeMap的紅黑樹理解注解. 2017.02.16 by 何錦彬  JDK,1.7.51<br>  <br>/** From CLR */
private void fixAfterInsertion(Entry<K, V> x) { //新加入紅黑樹的默認節(jié)點就是紅色
x.color = RED;
/**
* 1. 如為根節(jié)點直接跳出
*/
while (x != null && x != root && x.parent.color == RED) { if (parentOf(x) == leftOf(parentOf(parentOf(x)))) { //如果X的父節(jié)點(P)是其父節(jié)點的父節(jié)點(G)的左節(jié)點
//即 下面這種情況
/**
* G
* P(RED) U
*/
//獲取其叔(U)節(jié)點
Entry<K, V> y = rightOf(parentOf(parentOf(x)));
if (colorOf(y) == RED) {
// 這種情況,對應(yīng)下面 圖:情況一
/**
* G
* P(RED) U(RED)
* X
*/
//如果叔節(jié)點是紅色的(父節(jié)點有判斷是紅色). 即是雙紅色,比較好辦,通過改變顏色就行. 把P和U都設(shè)置成黑色然后,X加到P節(jié)點。 G節(jié)點當作新加入節(jié)點繼續(xù)迭代
setColor(parentOf(x), BLACK);
setColor(y, BLACK);
setColor(parentOf(parentOf(x)), RED);
x = parentOf(parentOf(x));
} else {
//處理紅父,黑叔的情況
if (x == rightOf(parentOf(x))) {
// 這種情況,對應(yīng)下面 圖:情況二
/**
* G
* P(RED) U(BLACK)
* X
*/
//如果X是右邊節(jié)點
x = parentOf(x);
// 進行左旋
rotateLeft(x);
}
//左旋后,是這種情況了,對應(yīng)下面 圖:情況三
/**
* G
* P(RED) U(BLACK)
* X
*/ // 到這,X只能是左節(jié)點了,而且P是紅色,U是黑色的情況
//把P改成黑色,G改成紅色,以G為節(jié)點進行右旋
setColor(parentOf(x), BLACK);
setColor(parentOf(parentOf(x)), RED);
rotateRight(parentOf(parentOf(x)));
}
} else {
//父節(jié)點在右邊的
/**
* G
* U P(RED)
*/
//獲取U
Entry<K, V> y = leftOf(parentOf(parentOf(x))); if (colorOf(y) == RED) {
//紅父紅叔的情況
/**
* G
* U(RED) P(RED)
*/
setColor(parentOf(x), BLACK);
setColor(y, BLACK);
setColor(parentOf(parentOf(x)), RED);
//把G當作新插入的節(jié)點繼續(xù)進行迭代
x = parentOf(parentOf(x));
} else {
//紅父黑叔,并且是右父的情況
/**
* G
* U(RED) P(RED)
*/
if (x == leftOf(parentOf(x))) {
//如果插入的X是左節(jié)點
/**
* G
* U(BLACK) P(RED)
* X
*/
x = parentOf(x);
//以P為節(jié)點進行右旋
rotateRight(x);
}
//右旋后
/**
* G
* U(BLACK) P(RED)
* X
*/
setColor(parentOf(x), BLACK);
setColor(parentOf(parentOf(x)), RED);
//以G為節(jié)點進行左旋
rotateLeft(parentOf(parentOf(x)));
}
}
}
//紅黑樹的根節(jié)點始終是黑色
root.color = BLACK;
}

  

其實就是一顆2-3-4樹變種,紅黑樹詳情可以看我上一篇

而且JDK8的hashMap鏈表后,鏈表的深度超過8也是轉(zhuǎn)換成紅黑樹的存儲,個人是認為轉(zhuǎn)換成紅黑樹后,hashMap的擴容條件是有問題了,應(yīng)該加入是否有紅黑樹的判斷

總結(jié)

以上是生活随笔為你收集整理的JAVA的那些数据结构实现总结,实现,扩容说明的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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