Java基礎 集合框架 隊列架構 雙端隊列 Deque

雙端隊列 Deque

  • Deque 方法簡介
  • Deque 核心特點
  • Deque實現類 ArrayDeque
    • ArrayDeque 構造方法
    • ArrayDeque 的數據結構及實現原理
    • ArrayDeque 方法介紹
    • ArrayDeque 核心特性
    • ArrayDeque 總結
    • ArrayDeque 使用樣例代碼
  • Deque實現類 LinkedList
  • Deque實現類 ConcurrentLinkedDeque (非阻塞線程安全)
    • ConcurrentLinkedDeque 核心特性
    • ConcurrentLinkedDeque 方法
    • ConcurrentLinkedDeque 數據結構和實現原理
    • ConcurrentLinkedDeque 總結
    • ConcurrentLinkedDeque 代碼使用示例
  • ArrayDeque 與 LinkedList 對比
  • Deque總結

雙端隊列的核心特點在于 在隊列的兩端進行插入和刪除操作,在隊列的 前端Front后端Rear 高效地進行插入和刪除操作。它融合了 普通隊列(先進先出 - FIFO)棧(后進先出 - LIFO)的特性

public interface Deque<E> extends Queue<E> {}

Deque 方法簡介

比起基本隊列Deque 為每種操作(插入、移除、檢查)在隊列的兩端(頭部和尾部)都提供了兩組方法。一組在操作失敗時拋出異常,另一組則返回特殊值(通常是 nullfalse)。

操作頭部 (Front/First)尾部 (Rear/Last)
插入addFirst(e) / offerFirst(e)addLast(e) / offerLast(e)
失敗拋異常 / 失敗返回 false失敗拋異常 / 失敗返回 false
移除removeFirst() / pollFirst()removeLast() / pollLast()
空隊列拋異常 / 空隊列返回 null空隊列拋異常 / 空隊列返回 null
檢查getFirst() / peekFirst()getLast() / peekLast()
查看不刪除空隊列拋異常 / 空隊列返回 null空隊列拋異常 / 空隊列返回 null
棧操作push(e) (等價于 addFirst(e))
pop() (等價于 removeFirst())
peek() (等價于 peekFirst())
隊列操作remove() (等價于 removeFirst())add(e) (等價于 addLast(e))
(繼承自Queue)poll() (等價于 pollFirst())offer(e) (等價于 offerLast(e))
element() (等價于 getFirst())
peek() (等價于 peekFirst())
其他removeFirstOccurrence(Object o)removeLastOccurrence(Object o)
從前往后移除第一個匹配元素,成功返回true從后往前移除第一個匹配元素,成功返回true
contains(Object o)size()
iterator()descendingIterator() (從尾到頭遍歷)

Deque 核心特點

1.雙端操作
這是Deque的核心。你可以在隊列的頭部尾部執行插入、刪除和檢查操作

2.替代角色

  • 作為隊列 (FIFO): 使用 addLast(e) / offerLast(e) 添加元素到尾部,使用 removeFirst() / pollFirst() 從頭部移除元素
  • 作為棧 (LIFO): 使用 push(e) / addFirst(e) 添加元素到頭部(壓棧),使用 pop() / removeFirst() 從頭部移除元素(彈棧),使用 peek() / peekFirst() 查看棧頂元素而不移除,使用push(e), pop(), peek()時,明確表示你在將Deque當作棧使Deque 是官方推薦替代遺留 Stack 類的方案

3.容量限制
某些 Deque 實現(如 ArrayDeque)可能有固定容量限制。嘗試在滿隊列中添加元素可能會導致異常或返回特殊值(取決于具體方法)

4.Null元素
Deque 的實現類可以允許或不允許null元素。ArrayDeque不允許null元素,而LinkedList允許。使用 null 元素時要特別小心,因為某些方法(如 removeFirstOccurrence(null))可能會產生歧義

5.非線程安全
Deque的標準實現類(ArrayDeque, LinkedList)不是線程安全的。線程安全方式使用外部同步機制(如 Collections.synchronizedDeque())或使用并發包下的實現(如 LinkedBlockingDeque

Deque實現類 ArrayDeque

ArrayDeque實現了Deque接口,基于動態數組的數據提供了雙端隊列的功能

public class ArrayDeque<E> extends AbstractCollection<E>implements Deque<E>, Cloneable, Serializable

ArrayDeque 構造方法

1.無參構造默認容量 16

// 創建一個初始容量為16的空隊列
Deque<String> names = new ArrayDeque<>(); 

2.創建一個具有指定初始容量的空雙端隊列

//預分配足夠空間存放大約1000個讀數
Deque<Integer> sensorReadings = new ArrayDeque<>(1000); // 但注意的是 自動調整為2的冪
ArrayDeque<Integer> deque2 = new ArrayDeque<>(100); // 實際容量128

3.創建一個包含指定集合 c 中所有元素的雙端隊列
元素的順序由集合的迭代器返回順序決定

List<String> list = Arrays.asList("Apple", "Banana", "Orange");
// 創建包含["Apple", "Banana", "Orange"]的隊列
Deque<String> fruitDeque = new ArrayDeque<>(list); 重要提示:
如果傳入的集合 c 是 null,會拋出 NullPointerException。
如果傳入的集合 c 中包含 null 元素,在添加過程中(調用 c.iterator().next() 時)
會拋出 NullPointerException,因為 ArrayDeque 不允許 null 元素

ArrayDeque 的數據結構及實現原理

數據結構

// 關鍵字段
transient Object[] elements; // 存儲元素的數組
transient int head;          // 頭部指針(指向當前首元素)
transient int tail;          // 尾部指針(指向下一個插入位置)

動態循環數組示意圖
動態數組:數組的大小可隨著數據量進行擴容
循環數組:數組的任何一點都可以被看作是起點或者終點

添加節點流程圖

假設初始容量為 4(實際最小容量為 8,但為簡化演示使用 4)初始狀態
數組:[null, null, null, null]
head = 0, tail = 0(空隊列)
索引:  0     1     2     3[null, null, null, null]↑head/tail步驟 1: 尾部添加 A (addLast("A"))
在tail位置插入A,tail后移:tail = (0 + 1) & 3 = 1
索引:  0     1     2     3["A", null, null, null]↑head ↑tail步驟 2: 尾部添加 B (addLast("B"))
在 tail 位置插入 B,tail 后移:tail = (1 + 1) & 3 = 2
索引:  0     1     2     3["A", "B", null, null]↑head       ↑tail步驟 3: 頭部添加 C (addFirst("C"))
head 前移:head = (0 - 1) & 3 = 3(循環到末尾) 在 head 位置插入 C
索引:  0     1     2     3["A", "B", null, "C"]↑tail ↑head步驟 4: 尾部添加 D (addLast("D"))
在 tail 位置插入 Dtail 后移:tail = (2 + 1) & 3 = 3
此時 head == tail,觸發擴容!
索引:  0     1     2     3["A", "B", "D", "C"]↑head/tail? (實際 head=3, tail=3)步驟 5: 擴容(關鍵步驟)
計算新容量:原容量 4 → 新容量 8(翻倍)
創建新數組:[null, null, null, null, null, null, null, null]
復制元素(按邏輯順序重排)1.從原head開始:復制索引3"C" → 新數組索引 02.繼續循環:復制索引0"A" → 新數組索引 13.復制索引1"B" → 新數組索引 24.復制索引2"D" → 新數組索引 3
重置指針:
head = 0(新數組頭部)
tail = 4(新數組尾部下一個空位)
新數組索引: 0    1    2    3    4    5    6    7["C", "A", "B", "D", null, null, null, null]↑head                ↑tail再新增節點
頭部添加 E (addFirst("E"))
head 前移:head = (0 - 1) & 7 = 7(循環到末尾),在 head 位置插入 E
索引:  0    1    2    3    4      5     6    7["C", "A", "B", "D", null, null, null, "E"]↑tail             ↑head尾部添加 F (addLast("F"))
在 tail 位置插入 F,tail 后移:tail = (4 + 1) & 7 = 5
索引: 0    1    2    3    4     5     6     7["C", "A", "B", "D", "F", null, null, "E"]↑tail        ↑head直到兩種會師 那就再次擴容 2倍擴容

刪除節點流程圖

頭部移除 (removeFirst())
取出 head 位置元素 "E",置空 head 位置
head 后移:head = (7 + 1) & 7 = 0
索引:  0    1    2    3    4    5     6     7["C", "A", "B", "D", "F", null, null, null]↑head                    ↑tail尾部移除 (removeLast())
tail 前移:tail = (5 - 1) & 7 = 4
取出 tail 位置元素 "F" 置空 tail 位置
索引:   0    1    2    3    4    5     6     7["C", "A", "B", "D", null, null, null, null]↑head     		  ↑tai

ArrayDeque 方法介紹

操作方法時間復雜度說明
頭部插入addFirst(E), push(E)O(1)插入失敗拋出異常
offerFirst(E)O(1)插入失敗返回 false
頭部移除removeFirst(), pop()O(1)空隊列拋出異常
pollFirst()O(1)空隊列返回 null
頭部查看getFirst(), peek()O(1)空隊列拋出異常
peekFirst()O(1)空隊列返回 null
尾部插入addLast(E), add(E)O(1)插入失敗拋出異常
offerLast(E), offer(E)O(1)插入失敗返回 false
尾部移除removeLast()O(1)空隊列拋出異常
pollLast()O(1)空隊列返回 null
尾部查看getLast()O(1)空隊列拋出異常
peekLast()O(1)空隊列返回 null
大小檢查size()O(1)通過 head 和 tail 計算
包含檢查contains(Object)O(n)線性搜索
清空clear()O(n)遍歷數組置 null

ArrayDeque 核心特性

  1. 基于循環數組實現
    • 底層使用動態數組(Object[])存儲元素。
    • 通過兩個指針(head 和 tail)實現循環數組,head 指向隊列的第一個元素,tail 指向隊列末尾的下一個空位。
    • 當數組滿時會自動擴容(通常翻倍),并將元素復制到新數組。
  2. 高效的頭尾操作
    • 隊列兩端(頭部和尾部)添加或移除元素的時間復雜度為 O(1)(攤銷時間,因涉及擴容操作
    • 具體方法包括:
      • 頭部操作:addFirst(), offerFirst(), removeFirst(), pollFirst(), getFirst(), peekFirst()
      • 尾部操作:addLast(), offerLast(), removeLast(), pollLast(), getLast(), peekLast()
  3. 不允許 null 元素
    • 試圖添加 null 元素會拋出 NullPointerException。
  4. 非線程安全
    • 不是線程安全的類,如果需要在多線程環境下使用,必須通過外部同步機制(如 Collections.synchronizedDeque)來保證線程安全。
  5. 迭代快速失敗(Fail-Fast)
    • 迭代器是快速失敗的,如果在迭代過程中隊列被修改(除了通過迭代器自身的 remove 方法),會拋出 ConcurrentModificationException。
  6. 用作棧和隊列
    • 作為棧使用時(后進先出,LIFO),推薦使用 push(等同于 addFirst)和 pop(等同于 removeFirst)方法。
    • 作為隊列使用時(先進先出,FIFO),推薦使用 add(等同于 addLast)和 remove(等同于 removeFirst)或 offerpoll 方法。
  7. 性能優勢
    • 相比 LinkedList,ArrayDeque 在大多數場景下有更好的性能(尤其作為隊列或棧),因為基于數組實現,內存局部性更好,減少了指針操作的開銷。
  8. 初始容量
    • 默認初始容量為 16,也可以指定初始容量(必須是 2 的冪,如果不是,會自動調整為最接近的 2 的冪)。
    • 擴容策略:當數組滿時,容量翻倍(變為原來的 2 倍)。
  9. 元素順序
    • 迭代順序是從頭部(head)到尾部(tail),即隊列中元素的順序

ArrayDeque 總結

使用場景

場景推薦操作
FIFO 隊列offerLast(e)pollFirst()
LIFO 棧push(e) (=addFirst(e)) , pop() (=removeFirst())
滑動窗口頭尾快速插入/刪除(如 LeetCode 239)
任務調度高效管理待執行任務隊列
歷史記錄固定容量實現 LRU(需配合移除邏輯)

注意事項

場景原因
需要存儲 null設計禁止 null 元素
高頻隨機訪問按索引訪問中間元素需遍歷(改用 ArrayList
多線程無鎖環境非線程安全(改用 ConcurrentLinkedDequeLinkedBlockingDeque
精確控制容量增長擴容策略固定為翻倍(若需定制策略需自行實現)

ArrayDeque 使用樣例代碼

// 1. 作為棧使用(LIFO)
Deque<Integer> stack = new ArrayDeque<>();
stack.push(1);      // addFirst(1)
stack.push(2);
int top = stack.pop(); // removeFirst() → 2// 2. 作為隊列使用(FIFO)
Deque<String> queue = new ArrayDeque<>(1000); // 預分配容量
queue.offer("A");   // addLast("A")
queue.offer("B");
String first = queue.poll(); // removeFirst() → "A"// 3. 雙端操作
ArrayDeque<Character> deque = new ArrayDeque<>();
deque.addFirst('X'); // [X]
deque.addLast('Y');  // [X, Y]
deque.removeFirst(); // [Y]
deque.removeLast();  // []

Deque實現類 LinkedList

LinkedList是整個集合框架中最靈活的類之一,因為它同時實現了List Qeque Deque 三個數據結構
LinkedList詳情介紹鏈接

Deque實現類 ConcurrentLinkedDeque (非阻塞線程安全)

ConcurrentLinkedDeque是線程安全的無界雙端隊列,采用無鎖算法CAS實現,支持在隊列兩端進行高效并發操作。它是ConcurrentLinkedQueue的雙端隊列版本

public class ConcurrentLinkedDeque<E>extends AbstractCollection<E>implements Deque<E>, java.io.Serializable {}

基本隊列的非阻塞線程安全ConcurrentLinkedQueue 對比

特性ConcurrentLinkedDequeConcurrentLinkedQueue
操作端雙端(頭尾操作)單端(尾部入隊,頭部出隊)
特殊方法addFirst(), removeLast()
數據結構雙向鏈表單向鏈表
內存開銷更高(每個節點兩個指針)較低
使用場景更廣泛標準隊列場景

ConcurrentLinkedDeque 核心特性

1.線程安全:基于無鎖算法(CAS)實現
2.雙端操作:支持隊列頭部和尾部的插入/移除
3.無界隊列:理論上可無限擴展(受內存限制)
4.非阻塞:操作不會導致線程阻塞
5.FIFO/LIFO 混合:可作為隊列或棧使用
6.不允許 null 元素:插入 null 會拋出 NullPointerException

阻塞和非阻塞的主要區別在于是否等待對方響應
阻塞調用是指調用結果返回之前,當前線程會被掛起,一直處于等待消息通知,不能執行其他業務
非阻塞調用指在不能立刻得到結果之前,該調用不會阻塞當前線程

ConcurrentLinkedDeque 是非阻塞線程的特性區別對比 阻塞線程的類

特性阻塞隊列 (如 ArrayBlockingQueue)非阻塞隊列 (ConcurrentLinkedDeque)
線程掛起競爭失敗時掛起等待失敗時自旋重試,無掛起
開銷上下文切換開銷大無上下文切換,僅 CPU 自旋
吞吐量高競爭下下降顯著高并發場景下更優

簡單來說:阻塞的競爭失敗掛起等待,非阻塞的不掛起不斷重試直到成功,所以性能開銷更大點

ConcurrentLinkedDeque 方法

頭部操作

  • void addFirst(E e) / boolean offerFirst(E e):頭部插入元素
  • E removeFirst() / E pollFirst():移除并返回頭部元素
  • E getFirst() / E peekFirst():查看但不移除頭部元素

尾部操作

  • void addLast(E e) / boolean offerLast(E e):尾部插入元素
  • E removeLast() / E pollLast():移除并返回尾部元素
  • E getLast() / E peekLast():查看但不移除尾部元素

通用操作

  • boolean add(E e):尾部添加(等價于 addLast
  • E remove():頭部移除(等價于 removeFirst
  • E element() / E peek():查看頭部元素

ConcurrentLinkedDeque 數據結構和實現原理

數據結構:雙向鏈表節點
雙向鏈表節點結構

private static final class Node<E> {volatile Node<E> prev;  // 前驅指針volatile E item;        // 存儲元素volatile Node<E> next;  // 后繼指針// CAS 操作方法boolean casItem(E cmp, E val) { /*...*/ }void lazySetNext(Node<E> val) { /*...*/ }boolean casNext(Node<E> cmp, Node<E> val) { /*...*/ }// ... 類似的前驅指針操作方法
}

隊列頭尾指針分離

   private transient volatile Node<E> head;private transient volatile Node<E> tail;

實現原理
核心點
1.數據結構:雙向鏈表節點(Node)
2.無鎖算法:使用CAS操作更新指針
3.頭尾指針:volatile修飾的頭節點(head)和尾節點(tail)
4.協作式刪除機制:邏輯刪除(標記item為null)和物理刪除(解除鏈接)
5.一致性:弱一致性迭代器和視圖
6.惰性更新策略:頭尾指針不總是精確指向端點
7.最終一致性:通過后續操作逐步修正位置

已元素刪除算法(以 pollFirst 為例)

public E pollFirst() {restartFromHead:for (;;) {// 步驟1:定位頭節點Node<E> h = head, p = h;// 步驟2:查找首個有效節點while (p.item == null) {Node<E> next = p.next;if (next == null) return null;  // 隊列為空p = next;}// 步驟3:邏輯刪除 (標記item為null)if (!p.casItem(p.item, null)) continue;// 步驟4:物理解除鏈接Node<E> next = p.next;if (next != null && next.prev == p) {next.casPrev(p, p.prev);  // 更新后繼的前驅}Node<E> prev = p.prev;if (prev != null && prev.next == p) {prev.casNext(p, p.next);  // 更新前驅的后繼}// 步驟5:更新頭指針if (p != h) {updateHead();  // 惰性更新head}return p.item;}
}

協作式刪除節點
在步驟3:邏輯刪除 (標記item為null)

// 在指針中嵌入狀態信息(實際通過節點狀態實現)
if (node.item == null) {// 節點已被刪除,需要特殊處理helpUnlink(node);  // 協助解除鏈接continue;         // 重試操作
}

當線程A嘗試刪除節點X時:先將 X.item 置為 null(邏輯刪除)
線程B若發現 X.item == null:主動調用 helpUnlink(x) 協助物理解除鏈接,更新相鄰節點的指針
減少不必要的CAS操作

線程A: 設置X.item=null
線程B: 發現X.item=null
線程B: 嘗試更新X.prev.next
線程B: 嘗試更新X.next.prev
物理解除鏈接成功

迭代器實現原理:弱一致性迭代器

public Iterator<E> iterator() {return new Itr();
}private class Itr implements Iterator<E> {private Node<E> nextNode;private E nextItem;Itr() {advance();  // 初始化時獲取首個有效節點}void advance() {// 從當前節點開始查找下一個有效節點do {nextNode = (nextNode == null) ? first() : nextNode.next;} while (nextNode != null && nextNode.item == null);nextItem = (nextNode != null) ? nextNode.item : null;}
}

特點:
快照隔離:迭代開始時獲取當前頭指針
跳過已刪除節點:自動過濾 item == null 的節點
弱一致性:可能反映迭代開始后的部分修改

惰性更新策略

//前向指針修正:
void fixPrev(Node<E> p) {for (;;) {Node<E> q = p.prev;Node<E> next = p.next;if (q != null && q.next != p) {q.casNext(q.next, p);  // 修復前驅的后繼}if (next != null && next.prev != p) {next.casPrev(next.prev, p);  // 修復后繼的前驅}// 檢查是否修復完成if ((q == null || q.next == p) && (next == null || next.prev == p)) {break;}}
}

修復后,最終一致性

設計亮點
1.無鎖并發:基于 Michael-Scott 算法的雙端擴展,使用 CAS 實現線程安全
2.惰性更新策略:不立即更新反向指針(允許暫時不一致), 后續操作會修復不一致狀態
3.刪除標記技術:協作刪除:線程A的物理刪除 和 后續線程B的物理刪除
4.自我修復機制:線程遇到不一致狀態時主動修復鏈表,保證最終一致性

ConcurrentLinkedDeque 總結

性能總結

操作時間復雜度并發性能
addFirst()O(1)極高
pollLast()O(1)
size()O(n)
contains()O(n)

注意事項

1.弱一致性方法

  • size() 需要遍歷整個鏈表,結果可能過時
  • contains() 可能返回瞬時狀態
  • 迭代器是弱一致性的

2.內存消耗

  • 每個元素需要額外兩個指針(prev/next)
  • 比單向鏈表多 50% 內存開銷

3.精確性要求

   // 不要依賴size()進行關鍵決策if (deque.size() > threshold) {// 這個判斷可能不可靠!}

適用場景

1.工作竊取算法

   // 工作者線程從自己隊列頭部獲取任務Runnable task = localDeque.pollFirst();// 當本地隊列為空時,從其他隊列尾部竊取if (task == null) {task = otherDeque.pollLast();}

2.多生產者-多消費者系統

  • 生產者可自由選擇頭部/尾部添加任務
  • 消費者可選擇從頭部/尾部獲取任務

3.實時事件處理系統

  • 新事件添加到頭部(高優先級)
  • 舊事件從尾部處理(低優先級)

4.并發緩存實現

  • 最近使用添加到頭部
  • 淘汰策略從尾部移除

最佳實踐

1.首選特定端方法

   // 明確意圖deque.offerFirst(item); // 比 push() 更清晰

2.空隊列處理

   // 使用poll而不是remove避免異常E item = deque.pollFirst();if (item != null) {// 處理元素}

3.批量處理優化

   // 批量提取多個元素List<E> batch = new ArrayList<>(BATCH_SIZE);while (batch.size() < BATCH_SIZE) {E item = deque.pollFirst();if (item == null) break;batch.add(item);}

和Deque其余子類 性能對比

操作ConcurrentLinkedDequeLinkedBlockingDequeArrayDeque (非線程安全)
頭部插入 (100線程)12 ms45 msN/A
尾部插入 (100線程)13 ms48 msN/A
頭部刪除 (100線程)11 ms42 msN/A
內存開銷 (100萬元素)~48 MB~32 MB~24 MB

ConcurrentLinkedDeque 是 Java 并發編程中的高級工具:

  • ? 優勢:高并發性能、雙端操作、無界容量
  • ?? 局限:內存開銷大、弱一致性方法
  • 💡 適用:工作竊取、多端生產者-消費者系統、需要雙端操作的并發場景

在需要高并發雙端操作的場景下,ConcurrentLinkedDeque 提供了最優秀的并發性能,是構建高性能并發系統的理想選擇

ConcurrentLinkedDeque 代碼使用示例

1.作為并發棧(LIFO)

ConcurrentLinkedDeque<String> stack = new ConcurrentLinkedDeque<>();// 壓棧
stack.push("Task1"); // addFirst
stack.push("Task2");// 彈棧
String task = stack.pop(); // removeFirst

2.作為雙端隊列

ConcurrentLinkedDeque<Integer> deque = new ConcurrentLinkedDeque<>();// 生產者A - 尾部添加
new Thread(() -> {for (int i = 0; i < 100; i++) {deque.addLast(i); // 尾部添加}
}).start();// 生產者B - 頭部添加
new Thread(() -> {for (int i = -1; i > -100; i--) {deque.addFirst(i); // 頭部添加}
}).start();// 消費者 - 頭部處理
new Thread(() -> {while (true) {Integer num = deque.pollFirst(); // 頭部取出if (num != null) {System.out.println("Processed: " + num);}}
}).start();

ArrayDeque 與 LinkedList 對比

特性ArrayDequeLinkedList
數據結構動態循環數組雙向鏈表
內存占用更緊湊(無節點開銷)每個元素額外24字節
隨機訪問O(n)O(n)(實際更慢)
迭代性能更高(緩存友好)較低
插入/刪除(頭尾)O(1) 分攤時間O(1)
插入/刪除(中間)O(n)O(1)(已知位置)
null 支持? 禁止? 允許
多線程安全? 需要外部同步? 需要外部同步
擴容成本較高(復制數組)

Deque總結

Deque 是一個功能強大且靈活的接口,統一了隊列和棧的抽象。它提供了豐富的雙端操作方法(包括異常拋出型和特殊值返回型)。ArrayDeque 通常是需要高效雙端操作且不需要 List 功能或 null 元素時的最佳選擇。LinkedList 在需要同時使用 DequeList 功能或需要 null 元素時是唯一選擇。理解不同方法的區別以及兩種主要實現的特性,對于正確有效地使用 Deque 至關重要。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/87066.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/87066.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/87066.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Spring】——事務、整合、注解

目錄 一.Spring與mybatis的整合 1.配置文件 ?編輯2. 二.事務 1.事務屬性 2.傳播屬性 3.異常屬性 4.常見配置 三.注解 1.什么是注解 2.Autowired 1.用戶自定義注解 ?編輯?編輯2.JDK類型注入value 3.Bean 1.對象的創建 2.對象創建次數 3.Bean注解的注入 1.自…

Linux 離線下安裝gcc、g++

描述 離線時編譯Redis、nginx等編譯包&#xff0c;需要gcc安裝包&#xff0c;評論提醒我 上傳補充 操作 1、進入gcc目錄&#xff0c;并執行安裝命令 rpm -ivh *.rpm --nodeps --force查看版本 gcc -v2、進入gcc-c目錄&#xff0c;并執行安裝 rpm -ivh *.rpm --nodeps --f…

融智學定律3:流動創造價值僅當跨域協同

關鍵公式意義&#xff1a; 人流方程中的 α/β 反映城市吸引力不對稱性 物流優化中的 η 實現時間價值貨幣化 金流模型的 σ(?) 捕捉市場情緒突變點 信息熵的 ∥gi??gj?∥ 度量知識勢差驅動 當五流在黎曼流形上滿足 ?_μ?T^μν0&#xff08;能量動量守恒&#xff09…

趣味數據結構之——數組

你們一定都聽說過它的故事…… 是的沒錯&#xff0c;就是一個蘿卜一個坑。??? 想象一下數組就是那個坑&#xff0c;那么定義數組就是在挖坑。 元素就是蘿卜。 坑就在那里(地上)&#xff0c;整整齊齊地排在那里。 于是數組最重要的一個特性就顯現出來了——隨機存取。還…

PR-2025《Scaled Robust Linear Embedding with Adaptive Neighbors Preserving》

核心思想分析 這篇論文的核心思想在于解決線性嵌入&#xff08;linear embedding&#xff09;與非線性流形結構之間的不匹配問題。傳統方法通過保留樣本點間的親和關系來提取數據的本質結構&#xff0c;但這種方法在某些情況下無法有效捕捉到數據的全局或局部特性。此外&#…

Redis-漸進式遍歷

之前使用的keys查找key,一次獲取到了所有的key,當key較多時,這個操作就有可能造成Redis服務器阻塞.特別是keys *操作. 于是可以通過漸進式遍歷,每次獲取部分key,通過多次遍歷,既查詢到了所有的key,又不會卡死服務器. 漸進式遍歷不是通過一個命令獲取到所有元素的,而是由一組命…

ISP Pipeline(3):Lens Shading Correction 鏡頭陰影校正

上一篇文章講的是&#xff1a;ISP Pipeline&#xff08;2&#xff09;&#xff1a; Black Level Compensation:ISP Pipeline&#xff08;2&#xff09;&#xff1a;Black Level Compensation 黑電平補償-CSDN博客 視頻&#xff1a;(4) Lens Shading Correction | Image Signal…

什么是WebAssembly(WASM)

WebAssembly&#xff08;WASM&#xff09; 是一種高性能的低級編程語言字節碼格式&#xff0c;可在網頁和非網頁環境中運行&#xff0c;支持多語言編譯&#xff0c;運行速度接近原生代碼。它在區塊鏈中的作用是&#xff1a;作為智能合約的執行引擎&#xff0c;被多條非以太坊鏈…

【C++】inline的作用

一、inline的作用 1.1函數內聯 作用?&#xff1a;建議編譯器將函數調用替換為函數體代碼&#xff0c;減少函數調用的開銷&#xff08;壓棧/跳轉&#xff09;。?注意?&#xff1a;這只是對編譯器的建議&#xff0c;編譯器可能忽略&#xff08;如函數體過大或遞歸&#xff0…

代碼隨想錄|圖論|04廣度優先搜索理論基礎

廣搜的使用場景 廣搜的搜索方式就適合于解決兩個點之間的最短路徑問題。 因為廣搜是從起點出發&#xff0c;以起始點為中心一圈一圈進行搜索&#xff0c;一旦遇到終點&#xff0c;記錄之前走過的節點就是一條最短路。 當然&#xff0c;也有一些問題是廣搜 和 深搜都可以解決…

Xposed框架深度解析:Android系統級Hook實戰指南

引言:Android系統定制化的革命性突破 在移動安全研究和系統優化領域,傳統的APP修改方案面臨??三重技術瓶頸??: ??逆向工程壁壘??:APK重打包方案需處理簽名校驗、代碼混淆等防護,平均耗時增加200%??兼容性挑戰??:Android碎片化導致設備適配率不足65%??功能…

大模型在通訊網絡中的系統性應用架構

一、網絡架構智能化重構?? ??1.1 空天地一體化組網優化?? 智能拓撲動態調整??&#xff1a;大模型通過分析衛星軌道數據、地面基站負載及用戶分布&#xff0c;實時優化天地一體化網絡拓撲。例如&#xff0c;在用戶密集區域&#xff08;如城市中心&#xff09;自動增強低…

軟件測試進階:Python 高級特性與數據庫優化(第二階段 Day6)

在掌握 SQL 復雜查詢和 Python 數據庫基礎操作后&#xff0c;第六天將深入探索Python 高級編程特性與數據庫性能優化。通過掌握 Python 的模塊與包管理、裝飾器等高級語法&#xff0c;結合數據庫索引優化、慢查詢分析等技術&#xff0c;提升測試工具開發與數據處理效率。 一、…

【NLP】自然語言項目設計04

目錄 04模型驗證 代碼架構核心設計說明 05運行推理 代碼架構核心設計說明 項目展望 項目簡介 訓練一個模型&#xff0c;實現歌詞仿寫生成 任務類型&#xff1a;文本生成&#xff1b; 數據集是一份歌詞語料&#xff0c;訓練一個模型仿寫歌詞。 要求 1.清洗數據。歌詞語料…

數據結構1 ——數據結構的基本概念+一點點算法

數據結構算法程序設計 什么是數據結構 數據&#xff08;data&#xff09;&#xff1a;符號集合&#xff0c;處理對象。 數據元素&#xff08;data element&#xff09;&#xff0c;由數據項&#xff08;data item&#xff09; 組成。 關鍵字&#xff08;key&#xff09;識別…

每日八股文7.1

每日八股-7.1 網絡1.能說說 TCP 報文頭部都包含哪些關鍵字段嗎&#xff1f;2.TCP 是如何確保數據傳輸的可靠性的&#xff1f;你能詳細談談嗎&#xff1f;3.你能解釋一下 TCP 滑動窗口是如何設計的&#xff1f;它主要解決了什么問題&#xff1f;4.TCP 協議的擁塞控制是如何實現的…

高性能 List 轉 Map 解決方案(10,000 元素)

文章目錄 前言一、問題背景&#xff1a;為什么List轉Map如此重要&#xff1f;二、基礎方法對比&#xff1a;Stream vs For循環三、性能優化關鍵點四、面試回答技巧 前言 遇到一個有意思的面試題&#xff0c;如標題所說&#xff0c;當10,000條數據的List需要轉Map&#xff0c;如…

今日行情明日機會——20250701

上證指數縮量收陽線&#xff0c;形成日線上漲中繼&#xff0c;個股上漲和下跌總體持平。 深證指數量能持續放大&#xff0c;即將回補缺口位&#xff0c;短線注意周三或周四的調整。 2025年7月1日漲停股主要行業方向分析 1. 芯片&#xff08;17家漲停&#xff0c;國產替代&…

P1312 [NOIP 2011 提高組] Mayan 游戲

題目描述 Mayan puzzle 是最近流行起來的一個游戲。游戲界面是一個 7 7 7 行 5 \times5 5 列的棋盤&#xff0c;上面堆放著一些方塊&#xff0c;方塊不能懸空堆放&#xff0c;即方塊必須放在最下面一行&#xff0c;或者放在其他方塊之上。游戲通關是指在規定的步數內消除所有…

Spring Boot 2 多模塊項目中配置文件的加載順序

Spring Boot 2 多模塊項目中配置文件的加載順序 在 Spring Boot 2 多模塊項目中&#xff0c;配置文件的加載遵循特定的順序規則。了解這些規則對于正確管理多模塊應用的配置至關重要。 一、默認配置文件加載順序 Spring Boot 會按照以下順序加載 application.properties 或 …