【復習】Java集合

集合概念

集合與數組

數組是固定長度;集合是動態長度的數據結構,需要動態增加或刪除元素

數組可以包含基本數據類型和對象;集合只能包含對象

數組可以直接訪問元素;集合需要通過迭代器訪問元素

線程安全的集合?

java.util包:

  1. Vector:線程安全的動態數組,內部方法大部分都經過synchronized修飾
  2. Hashtable:線程安全的哈希表,內部方法大部分都經過synchronized修飾,這樣被所著的就是整個Table對象(底層是數組+鏈表)

并發Map:

  1. ConcurrentHashMap:
  • JDK7,ConcurrentMap加的是分段鎖(Segment鎖),每個分段鎖含有整個table的一部分,不同分段之間的并發互不影響【每個Segment都類似一個小的HashMap,對于插入、更新、刪除操作時,需要先定位到具體的Segment,再在Segment上加鎖】
  • JDK8,取消了Segment字段,直接在table元素上枷鎖,實現對每一行進行加鎖,進一步減少了并發沖突。主要通過volatile + CAS(樂觀鎖)或 synchronized(悲觀鎖)來實現的線程安全。

添加元素時,先判斷容器是否為空:

  • 為空:直接使用volatile + CAS來初始化
  • 不為空:根據存儲的元素計算該位置是否為空
    • 如果存儲的元素計算結果為空,利用CAS設置該節點
    • 如果存儲的元素計算結果不為空,使用synchronized,然后遍歷桶中的元素,并替換或新增節點到桶中,再判斷是否需要轉成紅黑樹。(當發生hash碰撞時說明容量不夠用或已經有大量線程訪問,因此使用synchronized來處理hash比CAS效率高)
  1. ConcurrentSkipListMap:實現了一個基于跳表(SkipList)算法的可排序的并發集合,通過維護多個指向其他元素的跳躍鏈接來實現高效查詢

并發Set:

  1. ConcurrentSkipListSet:線程安全的有序集合,底層是使用ConcurrentSkipListMap實現
  2. CopyOnWriteArraySet:線程安全的HashSet

并發List:

  1. CopyOnWriteArrayList:線程安全的ArrayList,底層通過一個數組保存數據,使用volatile關鍵字修飾數組,保證當前線程對數組對象重新賦值后,其他線程可以感知到;在寫入新元素時,會將原來的數組拷貝一份并讓原來數組的長度+1后就得到一個新數組,將元素放入新數組的最后一個位置,用新數組地址替換舊數組地址就能得到最新數據了;讀操作時不加鎖,一直都能讀的。

并發Queue:

  1. ConcurrentLinkedQueue:高并發場景下的隊列,通過無鎖(CAS)的方式,實現高并發狀態下的高性能。
  2. BlockingQueue:提供一種讀寫等待的機制,簡化多線程間的數據共享。

并發Deque:

  1. LinkedBlockingDeque:線程安全的雙端隊列,內部使用雙向鏈表結構

  2. ConcurrentLinkedQueue:基于鏈表節點的無限并發鏈表,可以安全的并發執行插入、刪除、訪問的操作

List

ArrayList是線程安全的嘛?有什么辦法可以把ArrayList變成線程安全的?

  1. 使用Collections類的synchronizedList方法將ArrayList包裝成線程安全的List
List<String> synchronizedList = Collections.synchronizedList(arrayList);
  1. 使用CopyOnWriteArrayList(這是一個線程安全的List)代替ArrayList
CopyOnWriteArrayList<String> copyOnWriteArrayList = new CopyOnWriteArrayList<>(arrayList);
  1. 使用Vector類代替ArrayList
Vector<String> vector = new Vector<>(arrayList);

Map

HashMap是線程安全的嗎?

HashMap不是線程安全的,在多線程環境下會存在以下問題:

  • JDK7,采用數組+鏈表,多線程環境下,數組擴容時會存在Entry鏈死循環和數據丟失的問題
  • JDK8,采用數組+鏈表+紅黑樹,解決了Entry鏈死循環和數據丟失的問題,但是多線程環境下,put元素會出現覆蓋的情況

保證線程安全:

  • 使用Collections.synchronizedMap同步加鎖的方式,還可以使用HashTable。
  • 使用ConcurrentHashMap。(JDK7使用分段鎖;JDK8使用CAS+synchronized)

HashMap一般用什么作為Key?為什么String適合做key?

用String做key,因為String對象是不可變的,一旦創建舊不能被修改,保證了key的穩定性。如果key是可變的,會導致hashCode和equals方法的不一致。

為什么HashMap要用紅黑樹而不是平衡二叉樹?

平衡二叉樹追求的是絕對平衡,導致每次在插入或刪除節點時,都需要通過左旋或右旋來調整,使它再次稱為一顆符合要求的平衡二叉樹

紅黑樹不支持這種完全平衡的規則, 犧牲了一部分的查找效率,但是可以換取一部分維持平衡狀態的成本。

HashMap的key可以為null嘛

HashMap使用hash()方法來計算key的哈希值,當key為空時,直接設置hash值為0,不走hashCode方法。

static final int hash(){return (key == null) ? 0 :hashCode()后處理
}

null作為key只能有一個,作為value可以有多個

重寫HashMap的equals和hashCode方法需要注意什么?

從HashMap中獲取值時,這些方法也會被用到,如果這些方法沒有被正確的實現,兩個不同的Key可能會產生相同的hashCode()和equals()輸出,HashMap會認為他們是相同的,把他們存在不同的地方。

重寫HashMap的equals方法不當會出現什么情況?

HashMap在比較元素時,先比較hashCode方法,如果hash值相同,再比較equals方法。

如果重寫hashCode方法,但是不重寫equals方法,會出現equals方法返回false,導致hashMap中存儲多個一樣的對象,與hashMap只有唯一的key的規范不符合。

HashMap在多線程下可能出現的問題?

  1. JDK7使用頭插法插入元素,多線程環境下,擴容時可能導致環形鏈表的出現,形成死循環。因此JDK8使用尾插法插入元素,在擴容時保持鏈表原本的順序不變,不會出現環形鏈表的問題

因為JDK7使用頭插法,對數組長度進行擴容時,如果原來是1->2->3,擴容后就會變成3->2->1

如果多個線程同時對HashMap進行擴容操作,可能會導致鏈表的指針混亂,形成環形鏈表。

  1. 多線程同時執行put操作,如果計算出來的索引位置是想通的,那會造成前一個key被后一個key覆蓋,從而導致元素丟失的問題

HashMap的擴容機制

在擴充HashMap時,不需要重新計算hash,只需要看看原來的hash值新增的那個bit是1還是0

索引 = (數組下標 - 1) & 哈希值

在這里插入圖片描述

  • 如果是0:索引沒變
  • 如果是1:索引 = 原索引 + 舊容量

所以HashMap的大小是2的n次方,這樣就不需要重新計算hash值。

HashMap和HashTable的區別

  1. HashMap線程不安全,可以存儲null的key和value,每次擴容成原來的2n,要保證線程安全也可以用ConcurrentHashMap。
  2. HashTable線程安全,所有的方法都加synchronized鎖,不可以有null的key和value,效率低,每次擴容為原來的2n + 1。

HashTable和ConcurrentHashMap的區別?

  • ConcurrentHashMap是線程安全的。讀操作不需要加鎖,寫操作需要加鎖。JDK7,ConcurrentHashMap采用數組 + 鏈表,并發控制用分段鎖;JDK8,ConcurrentHashMap采用數組 + 鏈表 + 紅黑樹,并發控制用CAS + synchronized
  • HashTable采用的是數組 + 鏈表,所有的方法都加synchronized鎖

Set

Set集合的特點?

Set集合是唯一的,不會有重復的元素。

向Set集合中插入元素時,先通過hashCode確定元素的存儲位置,再通過equals判斷是否存在相同的元素,如果存在不會再次插入。

有序Set是什么?

有序的Set是TreeSet和LinkedHashSet

  • TreeSet是基于紅黑樹來保證元素的自然順序
  • LinkedHashSet是基于雙向鏈表和哈希表的結合來保證元素添加的自然順序(可以記錄插入順序的集合,不僅保證元素的唯一性,還可以保證元素的插入順序)

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

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

相關文章

vue3 文件類型傳Form Data數據格式給后端

在 Vue 3 中&#xff0c;如果你想將文件&#xff08;例如上傳的 Excel 文件&#xff09;以 FormData 格式發送到后端&#xff0c;可以通過以下步驟實現。這種方式通常用于處理文件上傳&#xff0c;因為它可以將文件和其他數據一起發送到服務器。 首先&#xff0c;創建一個 Vue…

使用 INFINI Console 配置集群監控 Webhook 通知指南

在集群管理中&#xff0c;監控關鍵指標如CPU、內存、磁盤、JVM等是至關重要的。對于Easysearch及ES生態系統&#xff0c;還需要關注集群本身的指標&#xff0c;例如搜索延遲、集群狀態、節點移除等。INFINI Console不僅提供了默認的監控指標&#xff0c;還支持用戶自定義監控項…

WPF的頁面設計和實用功能實現

目錄 一、TextBlock和TextBox 1. 在TextBlock中實時顯示當前時間 二、ListView 1.ListView顯示數據 三、ComboBox 1. ComboBox和CheckBox組合實現下拉框多選 四、Button 1. 設計Button按鈕的邊框為圓角&#xff0c;并對指針懸停時的顏色進行設置 一、TextBlock和TextBox…

二級公共基礎之數據結構與算法篇(八)排序技術

目錄 前言 一、交換類排序 1.冒泡排序法 1. 冒泡排序的思想 2. 冒泡排序的實現步驟 3. 示例 4. 冒泡排序的特點 2.快速排序 1. 快速排序的核心思想 2. 快速排序的實現步驟 3. 示例代碼(C語言) 4. 快速排序的特點 二、插入類排序 1. 簡單插入排序 1.簡單插入排…

記錄一次 ALG 的處理過程

前幾天朋友找我幫忙&#xff0c;說碰到很大困難了&#xff0c;實際上&#xff0c;不過如此 現象是這樣的&#xff1a; FreeSWITCH mod_unimrcp 工作不正常 FS 和 mrcp-server 兩邊同時抓包&#xff0c;看到的是&#xff1a; sip 流程正常 FS TCP 連接到 mccp-server 失敗&…

【Linux網絡編程】IP協議格式,解包步驟

目錄 解析步驟 1.版本字段&#xff08;大小&#xff1a;4比特位&#xff09; 2.首部長度&#xff08;大小&#xff1a;4比特位&#xff09;&#xff08;單位&#xff1a;4字節&#xff09; &#x1f35c;細節解釋&#xff1a; 3.服務類型&#xff08;大小&#xff1a;8比特…

CSDN文章質量分查詢系統【贈python爬蟲、提分攻略】

CSDN文章質量分查詢系統 https://www.csdn.net/qc 點擊鏈接-----> CSDN文章質量分查詢系統 <------點擊鏈接 點擊鏈接-----> https://www.csdn.net/qc <------點擊鏈接 點擊鏈接-----> CSDN文章質量分查詢系統 <------點擊鏈接 點擊鏈…

HTML應用指南:利用GET請求獲取全國瀘溪河門店位置信息

隨著新零售業態的快速發展,門店位置信息的獲取變得越來越重要。作為新興烘焙品牌之一,瀘溪河自2013年在南京創立以來,一直堅持“健康美味,香飄世界”的企業使命,以匠人精神打造新中式糕點。為了更好地理解和利用這些數據,本篇文章將深入探討GET請求的實際應用,并展示如何…

如何在 React 中測試高階組件?

在 React 中測試高階組件可以采用多種策略&#xff0c;以下是常見的測試方法&#xff1a; 1. 測試高階組件返回的組件 高階組件本身是一個函數&#xff0c;它返回一個新的組件。因此&#xff0c;可以通過測試這個返回的組件來間接測試高階組件的功能。通常使用 Jest 作為測試…

R語言Stan貝葉斯空間條件自回歸CAR模型分析死亡率多維度數據可視化

全文鏈接&#xff1a;https://tecdat.cn/?p40424 在空間數據分析領域&#xff0c;準確的模型和有效的工具對于研究人員至關重要。本文為區域數據的貝葉斯模型分析提供了一套完整的工作流程&#xff0c;基于Stan這一先進的貝葉斯建模平臺構建&#xff0c;幫助客戶為空間分析帶來…

Casbin 權限管理介紹及在 Go 語言中的使用入門

引言 在現代軟件開發過程中&#xff0c;權限管理是一個至關重要的環節&#xff0c;它關系到系統的安全性和用戶體驗。Casbin 是一個強大的訪問控制庫&#xff0c;支持多種訪問控制模型&#xff0c;如 ACL&#xff08;訪問控制列表&#xff09;、RBAC&#xff08;基于角色的訪問…

快速入門——第三方組件element-ui

學習自嗶哩嗶哩上的“劉老師教編程”&#xff0c;具體學習的網站為&#xff1a;10.第三方組件element-ui_嗶哩嗶哩_bilibili&#xff0c;以下是看課后做的筆記&#xff0c;僅供參考。 第一節 組件間的傳值 組件可以有內部Data提供數據&#xff0c;也可由父組件通過prop方式傳…

【算法通關村 Day7】遞歸與二叉樹遍歷

遞歸與二叉樹遍歷青銅挑戰 理解遞歸 遞歸算法是指一個方法在其執行過程中調用自身。它通常用于將一個問題分解為更小的子問題&#xff0c;通過重復調用相同的方法來解決這些子問題&#xff0c;直到達到基準情況&#xff08;終止條件&#xff09;。 遞歸算法通常包括兩個主要…

樸素貝葉斯法

文章目錄 貝葉斯定理樸素貝葉斯法的學習與分類條件獨立假設樸素貝葉斯的后驗概率最大化準則樸素貝葉斯的基本公式 樸素貝葉斯法的參數估計極大似然估計 貝葉斯定理 前置知識&#xff1a;條件概率、全概率、貝葉斯公式 推薦視頻&#xff0c;看完視頻后搜索博客了解先驗概率、后…

《A++ 敏捷開發》- 20 從 AI 到最佳設計

“我們現在推行AIGC&#xff0c;服務端不需要UI交互設計的用AI自動產出代碼&#xff0c;你建議的結對編程、TDD等是否還適用&#xff1f;” 這兩年AI確實很火&#xff0c;是報紙、雜志的熱門話題。例如&#xff0c;HBR雜志從2024年9月至2025年二月份3期&#xff0c;里面有接近一…

GO系列-IO 文件操作

os io 判斷文件是否存在 func fileExist(filePath string) (bool, error) {_, err : os.Stat(filePath)if err nil {return true, nil}if os.IsNotExist(err) {return false, nil}return false, &CheckFileExistError{filePath} } 讀取文件內容 func readFileContext(…

rs485協議、電路詳解(保姆級)

起源 RS-485即Recommended Standard 485 協議的簡寫。1983年被電子工業協會(EIA)批準為一種通訊接口標準. 數據在通信雙方之間傳輸&#xff0c;本質是傳輸物理的電平&#xff0c;比方說傳輸5V的電壓 -1V的電壓信號&#xff0c;這些物理信號在傳輸過程中會受到很多干擾&#x…

JavaWeb-Tomcat服務器

文章目錄 Web服務器存在的意義關于Web服務器軟件Tomcat服務器簡介安裝Tomcat服務器Tomcat服務器源文件解析配置Tomcat的環境變量啟動Tomcat服務器一個最簡單的webapp(不涉及Java) Web服務器存在的意義 我們之前介紹過Web服務器進行通信的原理, 但是我們當時忘記了一點, 服務器…

【愚公系列】《Python網絡爬蟲從入門到精通》008-正則表達式基礎

標題詳情作者簡介愚公搬代碼頭銜華為云特約編輯,華為云云享專家,華為開發者專家,華為產品云測專家,CSDN博客專家,CSDN商業化專家,阿里云專家博主,阿里云簽約作者,騰訊云優秀博主,騰訊云內容共創官,掘金優秀博主,亞馬遜技領云博主,51CTO博客專家等。近期榮譽2022年度…

視覺分析之邊緣檢測算法

9.1 Roberts算子 Roberts算子又稱為交叉微分算法&#xff0c;是基于交叉差分的梯度算法&#xff0c;通過局部差分計算檢測邊緣線條。 常用來處理具有陡峭的低噪聲圖像&#xff0c;當圖像邊緣接近于正45度或負45度時&#xff0c;該算法處理效果更理想。 其缺點是對邊緣的定位…