JAVA基礎(chǔ)之?dāng)?shù)組和集合區(qū)別對(duì)比分析
一、數(shù)組:固定長(zhǎng)度的連續(xù)存儲(chǔ)容器
數(shù)組是 Java 中最基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)之一,適用于存儲(chǔ)固定長(zhǎng)度、相同數(shù)據(jù)類(lèi)型的元素,在內(nèi)存中占據(jù)連續(xù)空間,支持通過(guò)索引快速訪問(wèn)。
1.1 數(shù)組的核心特性
- 長(zhǎng)度不可變:數(shù)組在創(chuàng)建時(shí)必須顯式指定長(zhǎng)度(如
int[] arr = new int[5]),一旦創(chuàng)建,長(zhǎng)度無(wú)法動(dòng)態(tài)修改。若需增減元素,需手動(dòng)創(chuàng)建新數(shù)組并復(fù)制原元素。 - 元素類(lèi)型統(tǒng)一:數(shù)組中所有元素必須是同一數(shù)據(jù)類(lèi)型,可分為兩類(lèi):
- 基本數(shù)據(jù)類(lèi)型數(shù)組:存儲(chǔ)具體數(shù)值(如
int[]、double[]),默認(rèn)值為對(duì)應(yīng)基本類(lèi)型的零值(int為 0,double為 0.0,char為'\u0000')。 - 引用數(shù)據(jù)類(lèi)型數(shù)組:存儲(chǔ)對(duì)象的引用(如
String[]、Student[]),默認(rèn)值為null。
- 基本數(shù)據(jù)類(lèi)型數(shù)組:存儲(chǔ)具體數(shù)值(如
- 連續(xù)內(nèi)存存儲(chǔ):數(shù)組元素在內(nèi)存中按順序連續(xù)排列,索引(從 0 開(kāi)始)直接對(duì)應(yīng)元素在內(nèi)存中的偏移量,因此訪問(wèn)任意元素的時(shí)間復(fù)雜度為O(1),查詢(xún)效率極高。
- 默認(rèn)值初始化:無(wú)論是否顯式賦值,數(shù)組創(chuàng)建后都會(huì)自動(dòng)初始化所有元素為對(duì)應(yīng)類(lèi)型的默認(rèn)值,避免空指針或垃圾值問(wèn)題。
1.2 數(shù)組的聲明與初始化
數(shù)組的初始化分為 “動(dòng)態(tài)初始化”(先指定長(zhǎng)度,后賦值)和 “靜態(tài)初始化”(直接指定元素,長(zhǎng)度由元素個(gè)數(shù)決定),兩種方式不可同時(shí)使用。
// 1. 動(dòng)態(tài)初始化:指定長(zhǎng)度,元素為默認(rèn)值
int[] arr1 = new int[3]; // 長(zhǎng)度3,元素默認(rèn)值為0、0、0
arr1[0] = 10; // 手動(dòng)賦值第一個(gè)元素
// 2. 靜態(tài)初始化:指定元素,長(zhǎng)度自動(dòng)為3
int[] arr2 = new int[]{10, 20, 30};
// 簡(jiǎn)化寫(xiě)法(僅聲明時(shí)可用)
int[] arr3 = {10, 20, 30};
// 3. 引用數(shù)據(jù)類(lèi)型數(shù)組初始化
String[] strArr = new String[2]; // 默認(rèn)值為[null, null]
strArr[0] = "Java"; // 賦值第一個(gè)元素為字符串對(duì)象1.3 多維數(shù)組
多維數(shù)組本質(zhì)是 “數(shù)組的數(shù)組”,最常用的是二維數(shù)組,適用于存儲(chǔ)表格類(lèi)數(shù)據(jù)(如矩陣)。
- 二維數(shù)組的初始化:
// 1. 規(guī)則二維數(shù)組(每行長(zhǎng)度相同) int[][] matrix1 = new int[2][3]; // 2行3列,元素默認(rèn)值為0 matrix1[0][1] = 5; // 給第1行第2列元素賦值 // 2. 不規(guī)則二維數(shù)組(每行長(zhǎng)度可不同) int[][] matrix2 = new int[2][]; // 先指定行數(shù),不指定列數(shù) matrix2[0] = new int[3]; // 第1行長(zhǎng)度為3 matrix2[1] = new int[2]; // 第2行長(zhǎng)度為2
- 二維數(shù)組的遍歷:需通過(guò)嵌套循環(huán),外層遍歷 “行數(shù)組”,內(nèi)層遍歷 “行中的元素”。
for (int i = 0; i < matrix2.length; i++) { // 遍歷行
for (int j = 0; j < matrix2[i].length; j++) { // 遍歷每行的元素
System.out.print(matrix2[i][j] + " ");
}
System.out.println();
}1.4 Arrays 工具類(lèi)
Java 提供java.util.Arrays類(lèi),封裝了數(shù)組的常用操作(排序、查找、填充等),無(wú)需手動(dòng)實(shí)現(xiàn)復(fù)雜邏輯。
| 方法名 | 功能描述 | 示例 |
|---|---|---|
sort(數(shù)組) | 對(duì)數(shù)組進(jìn)行升序排序(基本類(lèi)型用快速排序,引用類(lèi)型用 TimSort) | Arrays.sort(arr1);(排序 int 數(shù)組) |
binarySearch(數(shù)組, 目標(biāo)值) | 二分查找目標(biāo)值在有序數(shù)組中的索引,未找到返回負(fù)數(shù) | int index = Arrays.binarySearch(arr2, 20); |
fill(數(shù)組, 填充值) | 將數(shù)組所有元素替換為指定填充值 | Arrays.fill(arr1, 5);(將 arr1 所有元素設(shè)為 5) |
toString(數(shù)組) | 將數(shù)組轉(zhuǎn)為字符串(如[10, 20, 30]),方便打印 | System.out.println(Arrays.toString(arr2)); |
copyOf(原數(shù)組, 新長(zhǎng)度) | 復(fù)制原數(shù)組,新數(shù)組長(zhǎng)度為指定值,超出部分用默認(rèn)值填充 | int[] newArr = Arrays.copyOf(arr2, 5);(新數(shù)組長(zhǎng)度 5,后 2 個(gè)元素為 0) |
1.5 數(shù)組的使用場(chǎng)景與局限性
- 適用場(chǎng)景:
- 存儲(chǔ)長(zhǎng)度固定、需頻繁查詢(xún)的數(shù)據(jù)。
- 底層實(shí)現(xiàn)其他數(shù)據(jù)結(jié)構(gòu)。
- 局限性:
- 長(zhǎng)度固定,無(wú)法動(dòng)態(tài)增減元素,增刪操作需手動(dòng)處理數(shù)組復(fù)制,效率低(時(shí)間復(fù)雜度 O (n))。
- 僅支持索引訪問(wèn),無(wú)內(nèi)置的增刪改查方法,需手動(dòng)實(shí)現(xiàn)(如判斷元素是否存在、刪除指定元素)。
- 無(wú)法直接存儲(chǔ)不同數(shù)據(jù)類(lèi)型的元素(如需存儲(chǔ)多種類(lèi)型,需用
Object[],但會(huì)丟失類(lèi)型安全性)。
二、集合:動(dòng)態(tài)長(zhǎng)度的靈活存儲(chǔ)框架
集合是 Java 為解決數(shù)組局限性設(shè)計(jì)的動(dòng)態(tài)數(shù)據(jù)結(jié)構(gòu),支持自動(dòng)擴(kuò)容、內(nèi)置增刪改查方法,且僅存儲(chǔ)引用數(shù)據(jù)類(lèi)型(基本類(lèi)型需通過(guò)包裝類(lèi)存儲(chǔ),如int對(duì)應(yīng)Integer)。
集合框架體系 ├─ Collection(單列集合:存儲(chǔ)單個(gè)元素) │ ├─ List(有序、可重復(fù)、有索引) │ │ ├─ ArrayList(底層數(shù)組,查詢(xún)快、增刪慢) │ │ └─ LinkedList(底層雙向鏈表,增刪快、查詢(xún)慢) │ └─ Set(無(wú)序、不可重復(fù)、無(wú)索引) │ ├─ HashSet(底層哈希表,增刪查快,無(wú)序) │ └─ TreeSet(底層紅黑樹(shù),自動(dòng)排序,有序) └─ Map(雙列集合:存儲(chǔ)鍵值對(duì)Key-Value) ├─ HashMap(底層哈希表,無(wú)序、鍵唯一,允許null鍵/值) └─ TreeMap(底層紅黑樹(shù),按鍵排序,有序,不允許null鍵)

2.1 Collection 接口:?jiǎn)瘟屑系捻攲右?guī)范
Collection是所有單列集合的父接口,定義了單列集合的通用方法,所有實(shí)現(xiàn)類(lèi)(如ArrayList、HashSet)都需遵守這些規(guī)范。
2.1.1 Collection 的通用方法
| 方法名 | 功能描述 | 示例代碼 |
|---|---|---|
boolean add(E e) | 向集合添加元素,成功返回true,失?。ㄈ?Set 重復(fù))返回false | List<String> list = new ArrayList<>(); list.add("Java"); |
boolean remove(Object o) | 刪除集合中指定元素,成功返回true,無(wú)此元素返回false | list.remove("Java"); |
boolean removeIf(Predicate filter) | 按條件刪除元素(Java 8+),過(guò)濾邏輯由Predicate接口實(shí)現(xiàn) | list.removeIf(s -> s.length() > 5);(刪除長(zhǎng)度 > 5 的元素) |
void clear() | 清空集合中所有元素,集合變?yōu)榭眨ㄩL(zhǎng)度 0) | list.clear(); |
boolean contains(Object o) | 判斷集合是否包含指定元素,包含返回true | boolean hasJava = list.contains("Java"); |
boolean isEmpty() | 判斷集合是否為空(長(zhǎng)度 0),空返回true | boolean isEmpty = list.isEmpty(); |
int size() | 返回集合中元素的個(gè)數(shù)(長(zhǎng)度) | int count = list.size(); |
Object[] toArray() | 將集合轉(zhuǎn)為數(shù)組,方便兼容數(shù)組操作 | Object[] arr = list.toArray(); |
2.1.2 Collection 的遍歷方式
遍歷是集合的核心操作,Collection提供 3 種常用遍歷方式,適用于不同場(chǎng)景:
方式 1:迭代器(Iterator)—— 支持遍歷中刪除元素
迭代器是Collection的內(nèi)置遍歷工具,通過(guò)iterator()方法獲取,支持在遍歷過(guò)程中安全刪除元素(避免ConcurrentModificationException異常)。
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("cherry");
// 1. 獲取迭代器對(duì)象
Iterator<String> iterator = list.iterator();
// 2. 遍歷:hasNext()判斷是否有下一個(gè)元素,next()獲取元素并移動(dòng)指針
while (iterator.hasNext()) {
String element = iterator.next();
if ("banana".equals(element)) {
// 迭代器的remove()方法:刪除當(dāng)前遍歷到的元素
iterator.remove();
}
System.out.println(element); // 輸出apple、banana、cherry(刪除后集合中無(wú)banana)
}方式 2:增強(qiáng) for 循環(huán)(for-each)—— 簡(jiǎn)潔的遍歷
增強(qiáng) for 循環(huán)是 Java 5 引入的簡(jiǎn)化語(yǔ)法,底層基于迭代器實(shí)現(xiàn),適用于 “僅遍歷,不修改集合結(jié)構(gòu)” 的場(chǎng)景,代碼簡(jiǎn)潔易讀。
// 語(yǔ)法:for (元素類(lèi)型 變量名 : 集合/數(shù)組)
for (String element : list) {
System.out.println(element); // 輸出apple、cherry(已刪除banana)
}
方式 3:Lambda 表達(dá)式 + forEach(Java 8+)—— 函數(shù)式遍歷
Java 8 為Collection新增forEach()方法,支持通過(guò) Lambda 表達(dá)式傳遞遍歷邏輯,代碼更簡(jiǎn)潔,適合函數(shù)式編程風(fēng)格。
// 語(yǔ)法:collection.forEach(元素 -> 遍歷邏輯)
list.forEach(element -> {
if (element.startsWith("a")) { // 篩選以"a"開(kāi)頭的元素
System.out.println(element); // 輸出apple
}
});
2.1.3 List 接口:有序可重復(fù)的單列集合
List是Collection的子接口,特點(diǎn)是有序(存儲(chǔ)與取出順序一致)、可重復(fù)(允許元素值相同)、有索引(支持通過(guò)索引訪問(wèn)元素),適用于需要 “按順序存儲(chǔ)、可通過(guò)位置操作” 的場(chǎng)景(如購(gòu)物車(chē)、任務(wù)列表)。
2.1.3.1 List 的核心特性
- 索引支持:可通過(guò)索引(0 開(kāi)始)訪問(wèn)、修改、刪除元素(如
get(0)獲取第一個(gè)元素,set(1, "new")修改第二個(gè)元素)。 - 元素可重復(fù):允許添加多個(gè)值相同的元素(如
list.add("Java"); list.add("Java"),集合中會(huì)存在兩個(gè) "Java")。 - 有序性:元素的存儲(chǔ)順序與取出順序完全一致(如按
A、B、C的順序添加,遍歷也會(huì)按A、B、C返回)。
2.1.3.2 ArrayList實(shí)現(xiàn)類(lèi):數(shù)組實(shí)現(xiàn)的高效查詢(xún)集合
ArrayList底層基于動(dòng)態(tài)數(shù)組實(shí)現(xiàn),默認(rèn)初始容量為 10,當(dāng)元素個(gè)數(shù)超過(guò)閾值(容量 × 負(fù)載因子 0.75)時(shí),會(huì)自動(dòng)擴(kuò)容為原容量的 1.5 倍(如 10→15→22...),適合頻繁查詢(xún)、少量增刪的場(chǎng)景。
(1)ArrayList 的構(gòu)造方法
| 構(gòu)造方法 | 功能描述 | 示例 |
|---|---|---|
ArrayList() | 創(chuàng)建默認(rèn)初始容量為 10 的空集合 | List<String> list = new ArrayList<>(); |
ArrayList(int initialCapacity) | 創(chuàng)建指定初始容量的空集合(避免頻繁擴(kuò)容) | List<String> list = new ArrayList<>(20);(初始容量 20) |
ArrayList(Collection<? extends E> c) | 將其他 Collection 集合轉(zhuǎn)為 ArrayList | Set<String> set = new HashSet<>(); List<String> list = new ArrayList<>(set); |
(2)ArrayList 的核心方法
索引相關(guān)操作:
List<String> list = new ArrayList<>();
list.add("apple"); // 末尾添加元素
list.add(1, "banana"); // 索引1處插入元素(原元素后移)
String first = list.get(0); // 獲取索引0的元素(apple)
list.set(0, "orange"); // 修改索引0的元素為orange
String removed = list.remove(1); // 刪除索引1的元素(banana),返回被刪除元素(3)ArrayList 的性能分析
- 查詢(xún)效率:通過(guò)索引直接訪問(wèn)元素,時(shí)間復(fù)雜度O(1),效率極高。
- 增刪效率:
- 末尾增刪:直接操作數(shù)組末尾,時(shí)間復(fù)雜度O(1)。
- 中間增刪:需移動(dòng)后續(xù)元素(如在索引 1 插入元素,需移動(dòng)索引 1 及之后的所有元素),時(shí)間復(fù)雜度O(n),效率低。
- 擴(kuò)容機(jī)制:擴(kuò)容時(shí)需創(chuàng)建新數(shù)組并復(fù)制原元素,頻繁擴(kuò)容會(huì)消耗性能,因此建議提前估算元素個(gè)數(shù),通過(guò)
ArrayList(int initialCapacity)指定初始容量。
2.1.3.3 LinkedList實(shí)現(xiàn)類(lèi):鏈表實(shí)現(xiàn)的高效增刪集合
LinkedList底層基于雙向鏈表實(shí)現(xiàn),每個(gè)元素(節(jié)點(diǎn))包含 “前驅(qū)節(jié)點(diǎn)引用、自身值、后繼節(jié)點(diǎn)引用”,無(wú)需連續(xù)內(nèi)存空間,適合頻繁增刪、少量查詢(xún)的場(chǎng)景(如隊(duì)列、棧)。
(1)LinkedList 的特有方法(操作首尾元素)
由于鏈表結(jié)構(gòu)的特性,LinkedList提供了直接操作首尾元素的方法,時(shí)間復(fù)雜度均為O(1):
LinkedList<String> list = new LinkedList<>();
list.addFirst("a"); // 鏈表開(kāi)頭添加元素
list.addLast("b"); // 鏈表末尾添加元素
String first = list.getFirst(); // 獲取開(kāi)頭元素(a)
String last = list.getLast(); // 獲取末尾元素(b)
String removedFirst = list.removeFirst(); // 刪除并返回開(kāi)頭元素(a)
String removedLast = list.removeLast(); // 刪除并返回末尾元素(b)(2)LinkedList 的性能分析
- 增刪效率:
- 首尾增刪:直接修改首尾節(jié)點(diǎn)的引用,時(shí)間復(fù)雜度O(1),效率極高。
- 中間增刪:需先通過(guò)遍歷找到目標(biāo)節(jié)點(diǎn)(時(shí)間復(fù)雜度 O (n)),再修改節(jié)點(diǎn)引用(O (1)),整體效率低于首尾操作。
- 查詢(xún)效率:無(wú)索引,查詢(xún)指定元素需從鏈表頭 / 尾開(kāi)始遍歷,時(shí)間復(fù)雜度O(n),效率低。
2.1.3.4 ArrayList 與 LinkedList 的對(duì)比選擇
| 對(duì)比維度 | ArrayList | LinkedList |
|---|---|---|
| 底層結(jié)構(gòu) | 動(dòng)態(tài)數(shù)組 | 雙向鏈表 |
| 查詢(xún)效率 | 高(O (1)) | 低(O (n)) |
| 首尾增刪 | 低(O (n),需擴(kuò)容 / 移動(dòng)元素) | 高(O (1)) |
| 中間增刪 | 低(O (n),需移動(dòng)元素) | 中(O (n),需遍歷找節(jié)點(diǎn)) |
| 內(nèi)存占用 | 連續(xù)內(nèi)存,可能有空閑空間(擴(kuò)容預(yù)留) | 非連續(xù)內(nèi)存,每個(gè)節(jié)點(diǎn)需存儲(chǔ)前后引用,內(nèi)存開(kāi)銷(xiāo)略大 |
| 適用場(chǎng)景 | 頻繁查詢(xún)、少量增刪(如商品列表、數(shù)據(jù)展示) | 頻繁首尾增刪(如隊(duì)列、棧)、少量查詢(xún) |
2.1.4 Set 接口:無(wú)序不可重復(fù)的單列集合
Set是Collection的子接口,特點(diǎn)是無(wú)序(存儲(chǔ)與取出順序可能不一致)、不可重復(fù)(元素值唯一)、無(wú)索引,適用于需要 “去重” 的場(chǎng)景(如用戶(hù) ID 列表、不重復(fù)的標(biāo)簽)。
2.1.4.1 Set 的核心特性(補(bǔ)充 Collection)
- 元素不可重復(fù):添加重復(fù)元素時(shí),
add()方法返回false,集合不會(huì)存儲(chǔ)重復(fù)值(去重邏輯由具體實(shí)現(xiàn)類(lèi)決定)。 - 無(wú)索引:不支持通過(guò)索引訪問(wèn)元素,因此無(wú)法使用普通
for循環(huán)遍歷,只能用迭代器、增強(qiáng)for或forEach。 - 無(wú)序性:
HashSet:完全無(wú)序,元素存儲(chǔ)順序與添加順序無(wú)關(guān)。TreeSet:有序,會(huì)按元素的 “自然順序” 或 “自定義比較器順序” 排序。
2.1.4.2 HashSet:哈希表實(shí)現(xiàn)的高效去重集合
HashSet 判斷元素是否重復(fù)的過(guò)程如下:
HashSet底層基于哈希表(數(shù)組 + 鏈表 / 紅黑樹(shù)) 實(shí)現(xiàn),是Set最常用的實(shí)現(xiàn)類(lèi),特點(diǎn)是增刪查效率高、完全無(wú)序、支持 null 元素。
(1)HashSet 的去重原理:hashCode () + equals ()

HashSet判斷元素是否重復(fù)的核心是 “先比哈希值,再比內(nèi)容”,需依賴(lài)元素的hashCode()和equals()方法,具體流程如下:
- 調(diào)用新增元素的
hashCode()方法,計(jì)算其哈希值,根據(jù)哈希值確定在哈希表中的 “桶位置”(數(shù)組索引)。 - 若該桶位置為空,直接將元素存入(無(wú)重復(fù))。
- 若該桶位置不為空(哈希沖突),則調(diào)用元素的
equals()方法,與桶中已有的元素逐一比較:- 若
equals()返回true:元素重復(fù),不存入。 - 若
equals()返回false:元素不重復(fù),將元素存入桶中(JDK 8 + 中,若桶中元素超過(guò) 8 個(gè),鏈表會(huì)轉(zhuǎn)為紅黑樹(shù),提升查詢(xún)效率)。
- 若
因此,為了確保 HashSet 能夠正確判斷元素的唯一性,需要重寫(xiě)元素類(lèi)的 hashCode() 和 equals() 方法。
(2)關(guān)鍵注意事項(xiàng)
- 若自定義類(lèi)(如
Student、Book)的對(duì)象要存入HashSet,必須重寫(xiě)hashCode()和equals()方法,否則會(huì)默認(rèn)使用Object類(lèi)的方法(hashCode()返回對(duì)象地址,equals()比較地址),導(dǎo)致無(wú)法正確去重。 - 重寫(xiě)規(guī)則:
- 若兩個(gè)對(duì)象
equals()返回true,則它們的hashCode()必須相等。 - 若兩個(gè)對(duì)象
hashCode()不相等,則equals()必須返回false(減少哈希沖突)。
- 若兩個(gè)對(duì)象
(3)HashSet 的構(gòu)造方法與常用方法
// 1. 構(gòu)造方法
HashSet<String> set1 = new HashSet<>(); // 默認(rèn)初始容量16,負(fù)載因子0.75
HashSet<String> set2 = new HashSet<>(20); // 指定初始容量
Set<String> temp = new ArrayList<>();
HashSet<String> set3 = new HashSet<>(temp); // 從其他Collection轉(zhuǎn)換
// 2. 常用方法(與Collection一致,無(wú)特有方法)
set1.add("Java");
set1.add("Python");
set1.add("Java"); // 重復(fù)元素,add()返回false,集合中僅存1個(gè)"Java"
boolean hasPython = set1.contains("Python"); // true
set1.remove("Python"); // 刪除元素,返回true
int size = set1.size(); // 12.1.4.3 TreeSet:紅黑樹(shù)實(shí)現(xiàn)的有序去重集合
TreeSet底層基于紅黑樹(shù)(一種自平衡二叉搜索樹(shù)) 實(shí)現(xiàn),特點(diǎn)是自動(dòng)排序、元素不可重復(fù)、不支持 null 元素,適用于需要 “去重且排序” 的場(chǎng)景(如按價(jià)格排序的商品列表、按學(xué)號(hào)排序的學(xué)生列表)。
(1)TreeSet 的排序方式
TreeSet的排序依賴(lài) “比較邏輯”,分為兩種方式:
自然排序(默認(rèn)):元素類(lèi)需實(shí)現(xiàn)Comparable接口,并重寫(xiě)compareTo()方法,定義元素的排序規(guī)則。
// 自定義Student類(lèi),實(shí)現(xiàn)Comparable接口,按學(xué)號(hào)升序排序
class Student implements Comparable<Student> {
private int id;
private String name;
// 構(gòu)造方法、getter/setter省略
@Override
public int compareTo(Student other) {
// 按id升序:當(dāng)前id - 其他id,返回正數(shù)則當(dāng)前元素在后,負(fù)數(shù)在前
return this.id - other.id;
}
}
// 使用TreeSet存儲(chǔ)Student,自動(dòng)按id升序排序
TreeSet<Student> studentSet = new TreeSet<>();
studentSet.add(new Student(3, "Alice"));
studentSet.add(new Student(1, "Bob"));
studentSet.add(new Student(2, "Charlie"));
// 遍歷輸出:Bob(id=1)、Charlie(id=2)、Alice(id=3)
for (Student s : studentSet) {
System.out.println(s.getName());
}自定義排序:若元素類(lèi)無(wú)法修改(如String、Integer),或需臨時(shí)改變排序規(guī)則,可在創(chuàng)建TreeSet時(shí)傳入Comparator接口實(shí)現(xiàn)類(lèi)(或 Lambda 表達(dá)式)。
// 存儲(chǔ)String,按字符串長(zhǎng)度降序排序(自定義比較器)
TreeSet<String> strSet = new TreeSet<>((s1, s2) -> {
// 按長(zhǎng)度降序:s2長(zhǎng)度 - s1長(zhǎng)度
return s2.length() - s1.length();
});
strSet.add("apple"); // 5個(gè)字符
strSet.add("banana"); // 6個(gè)字符
strSet.add("pear"); // 4個(gè)字符
// 遍歷輸出:banana(6)、apple(5)、pear(4)
for (String s : strSet) {
System.out.println(s);
}
(2)TreeSet 的關(guān)鍵注意事項(xiàng)
- 排序邏輯決定去重:
TreeSet判斷元素是否重復(fù)的依據(jù)是 “compareTo()或compare()方法返回 0”,若返回 0,認(rèn)為元素重復(fù),不存入。 - 不支持 null 元素:由于排序時(shí)無(wú)法比較
null與其他元素,存入null會(huì)拋出NullPointerException。 - 排序效率穩(wěn)定:紅黑樹(shù)的增刪查時(shí)間復(fù)雜度均為O(log n),適合需要排序且數(shù)據(jù)量較大的場(chǎng)景。
2.1.4.4 HashSet 與 TreeSet 的對(duì)比選擇
| 對(duì)比維度 | HashSet | TreeSet |
|---|---|---|
| 底層結(jié)構(gòu) | 哈希表(數(shù)組 + 鏈表 / 紅黑樹(shù)) | 紅黑樹(shù) |
| 排序特性 | 完全無(wú)序 | 有序(自然排序 / 自定義排序) |
| 增刪查效率 | 高(O (1),無(wú)哈希沖突時(shí)) | 中(O (log n)) |
| 去重依據(jù) | hashCode() + equals() | compareTo() / compare()返回 0 |
| null 支持 | 支持 1 個(gè) null 元素 | 不支持 null 元素 |
| 適用場(chǎng)景 | 僅需去重,無(wú)需排序(如用戶(hù) ID、標(biāo)簽) | 去重且需排序(如排序的商品價(jià)格、學(xué)號(hào)) |
2.2 Map 接口:鍵值對(duì)存儲(chǔ)的雙列集合
Map是 Java 中專(zhuān)門(mén)用于存儲(chǔ)鍵值對(duì)(Key-Value) 的雙列集合,每個(gè)鍵(Key)對(duì)應(yīng)唯一的值(Value),鍵不可重復(fù),值可重復(fù),適用于 “通過(guò)鍵快速查找值” 的場(chǎng)景(如用戶(hù)信息表:Key 為用戶(hù) ID,Value 為用戶(hù)對(duì)象)。
2.2.1 Map 的核心特性
- 鍵值對(duì)結(jié)構(gòu):每個(gè)元素是一個(gè) “鍵值對(duì)”(Java 中稱(chēng)為
Map.Entry對(duì)象),鍵與值一一對(duì)應(yīng),通過(guò)鍵可唯一確定值。 - 鍵唯一:同一個(gè)
Map中,鍵不能重復(fù)(重復(fù)添加會(huì)覆蓋原鍵對(duì)應(yīng)的值),值可以重復(fù)。 - 無(wú)索引:不支持通過(guò)索引訪問(wèn)元素,需通過(guò)鍵或鍵值對(duì)遍歷。
- 引用類(lèi)型存儲(chǔ):鍵和值都必須是引用數(shù)據(jù)類(lèi)型(基本類(lèi)型需用包裝類(lèi),如
int對(duì)應(yīng)Integer)。
2.2.2 Map 的通用方法
所有Map實(shí)現(xiàn)類(lèi)(如HashMap、TreeMap)都支持以下通用方法:
// 創(chuàng)建Map對(duì)象(以HashMap為例)
Map<String, Integer> scoreMap = new HashMap<>();
// 1. 添加/修改鍵值對(duì):鍵存在則覆蓋值,返回舊值;鍵不存在則添加,返回null
Integer oldScore = scoreMap.put("Alice", 95); // null(首次添加)
oldScore = scoreMap.put("Alice", 98); // 95(覆蓋舊值,返回舊值)
scoreMap.put("Bob", 88);
// 2. 刪除鍵值對(duì):根據(jù)鍵刪除,返回被刪除的值;鍵不存在返回null
Integer removedScore = scoreMap.remove("Bob"); // 88
// 3. 判斷存在性
boolean hasAlice = scoreMap.containsKey("Alice"); // true(判斷鍵是否存在)
boolean has98 = scoreMap.containsValue(98); // true(判斷值是否存在)
// 4. 獲取值:根據(jù)鍵獲取值,鍵不存在返回null
Integer aliceScore = scoreMap.get("Alice"); // 98
// 5. 清空與長(zhǎng)度
scoreMap.clear(); // 清空所有鍵值對(duì)
int size = scoreMap.size(); // 0(清空后長(zhǎng)度為0)
boolean isEmpty = scoreMap.isEmpty(); // true2.2.3 Map 的遍歷方式
Map的遍歷需圍繞 “鍵”“值”“鍵值對(duì)” 三種維度,共 3 種常用方式:
方式 1:遍歷鍵集(keySet ())—— 通過(guò)鍵找值
先獲取所有鍵的集合(keySet()),再遍歷鍵,通過(guò)get(Key)獲取對(duì)應(yīng)的值,適合僅需鍵和值的場(chǎng)景。
Map<String, Integer> scoreMap = new HashMap<>();
scoreMap.put("Alice", 95);
scoreMap.put("Bob", 88);
// 1. 獲取所有鍵的集合
Set<String> keys = scoreMap.keySet();
// 2. 遍歷鍵,獲取對(duì)應(yīng)值
for (String key : keys) {
Integer value = scoreMap.get(key);
System.out.println(key + " : " + value); // Alice:95, Bob:88
}方式 2:遍歷鍵值對(duì)集(entrySet ())—— 直接遍歷鍵值對(duì)
獲取所有鍵值對(duì)的集合(entrySet()),每個(gè)元素是Map.Entry對(duì)象,可直接通過(guò)getKey()和getValue()獲取鍵和值,效率比方式 1 高(無(wú)需多次調(diào)用get(Key))。
// 1. 獲取所有鍵值對(duì)的集合
Set<Map.Entry<String, Integer>> entrySet = scoreMap.entrySet();
// 2. 遍歷鍵值對(duì)
for (Map.Entry<String, Integer> entry : entrySet) {
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key + " : " + value); // Alice:95, Bob:88
}
// Lambda簡(jiǎn)化遍歷(Java 8+)
scoreMap.entrySet().forEach(entry -> {
System.out.println(entry.getKey() + " : " + entry.getValue());
});方式 3:遍歷值集(values ())—— 僅遍歷值
若僅需遍歷值,無(wú)需鍵,可通過(guò)values()獲取所有值的集合(Collection類(lèi)型),直接遍歷。
// 1. 獲取所有值的集合
Collection<Integer> values = scoreMap.values();
// 2. 遍歷值
for (Integer value : values) {
System.out.println(value); // 95, 88
}
2.2.4 HashMap:哈希表實(shí)現(xiàn)的高效鍵值對(duì)集合
HashMap是Map最常用的實(shí)現(xiàn)類(lèi),底層基于哈希表(數(shù)組 + 鏈表 / 紅黑樹(shù)) 實(shí)現(xiàn),特點(diǎn)是無(wú)序、鍵唯一、支持 null 鍵和 null 值、增刪查效率高,適用于大多數(shù)鍵值對(duì)存儲(chǔ)場(chǎng)景。
(1)HashMap 的核心特性
- 無(wú)序性:鍵值對(duì)的存儲(chǔ)順序與添加順序無(wú)關(guān),遍歷順序不固定。
- null 支持:允許 1 個(gè) null 鍵,允許多個(gè) null 值(如
map.put(null, 10); map.put(null, 20);會(huì)覆蓋為 null 鍵對(duì)應(yīng)的值 20)。 - 線程不安全:多線程環(huán)境下,若同時(shí)修改
HashMap(如添加 / 刪除元素),可能導(dǎo)致數(shù)據(jù)不一致或拋出ConcurrentModificationException,若需線程安全,可使用ConcurrentHashMap(推薦)或Collections.synchronizedMap(new HashMap<>())。
(2)HashMap 的擴(kuò)容機(jī)制
- 初始容量:默認(rèn)初始容量為 16(數(shù)組長(zhǎng)度),可通過(guò)構(gòu)造方法指定(如
new HashMap<>(32))。 - 負(fù)載因子:默認(rèn)值為 0.75,表示當(dāng)鍵值對(duì)數(shù)量超過(guò) “容量 × 負(fù)載因子”(如 16×0.75=12)時(shí),觸發(fā)擴(kuò)容。
- 擴(kuò)容規(guī)則:擴(kuò)容時(shí)將數(shù)組長(zhǎng)度擴(kuò)大為原容量的 2 倍(如 16→32→64...),并重新計(jì)算所有鍵的哈希值,將鍵值對(duì)遷移到新數(shù)組中(“重哈希”),頻繁擴(kuò)容會(huì)消耗性能,建議提前估算數(shù)據(jù)量,指定合適的初始容量。
(3)HashMap 的構(gòu)造方法
// 1. 默認(rèn)構(gòu)造:初始容量16,負(fù)載因子0.75
Map<String, Integer> map1 = new HashMap<>();
// 2. 指定初始容量:負(fù)載因子默認(rèn)0.75
Map<String, Integer> map2 = new HashMap<>(32);
// 3. 指定初始容量和負(fù)載因子
Map<String, Integer> map3 = new HashMap<>(32, 0.8f);
// 4. 從其他Map轉(zhuǎn)換
Map<String, Integer> tempMap = new HashMap<>();
tempMap.put("a", 1);
Map<String, Integer> map4 = new HashMap<>(tempMap);2.2.5 TreeMap:紅黑樹(shù)實(shí)現(xiàn)的有序鍵值對(duì)集合
TreeMap底層基于紅黑樹(shù)實(shí)現(xiàn),特點(diǎn)是按鍵排序、鍵唯一、不支持 null 鍵、有序,適用于需要 “按鍵排序” 的鍵值對(duì)場(chǎng)景(如按日期排序的日志記錄:Key 為日期,Value 為日志內(nèi)容)。
(1)TreeMap 的排序方式
與TreeSet類(lèi)似,TreeMap的排序依賴(lài)鍵的比較邏輯,分為兩種方式:
自然排序:鍵的類(lèi)需實(shí)現(xiàn)Comparable接口,并重寫(xiě)compareTo()方法,按鍵的自然順序排序。
// 鍵為Integer(已實(shí)現(xiàn)Comparable),按鍵升序排序
Map<Integer, String> treeMap1 = new TreeMap<>();
treeMap1.put(3, "C");
treeMap1.put(1, "A");
treeMap1.put(2, "B");
// 遍歷輸出:1:A, 2:B, 3:C(按鍵升序)
for (Map.Entry<Integer, String> entry : treeMap1.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
自定義排序:創(chuàng)建TreeMap時(shí)傳入Comparator接口實(shí)現(xiàn)類(lèi),自定義鍵的排序規(guī)則。
// 鍵為String,按字符串長(zhǎng)度降序排序
Map<String, Integer> treeMap2 = new TreeMap<>((k1, k2) -> {
return k2.length() - k1.length(); // 按鍵長(zhǎng)度降序
});
treeMap2.put("apple", 5);
treeMap2.put("banana", 6);
treeMap2.put("pear", 4);
// 遍歷輸出:banana:6, apple:5, pear:4(按鍵長(zhǎng)度降序)
for (Map.Entry<String, Integer> entry : treeMap2.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
(2)TreeMap 的特有方法(排序相關(guān))
由于TreeMap按鍵有序,提供了一些基于鍵排序的特有方法:
Map<Integer, String> treeMap = new TreeMap<>(); treeMap.put(1, "A"); treeMap.put(2, "B"); treeMap.put(3, "C"); treeMap.put(4, "D"); Integer firstKey = treeMap.firstKey(); // 獲取最小鍵(1) Integer lastKey = treeMap.lastKey(); // 獲取最大鍵(4) Integer lowerKey = treeMap.lowerKey(3); // 獲取小于3的最大鍵(2) Integer higherKey = treeMap.higherKey(3); // 獲取大于3的最小鍵(4) // 獲取鍵≥2且<4的子Map(包含2,不包含4) Map<Integer, String> subMap = treeMap.subMap(2, true, 4, false); // 子Map內(nèi)容:2:B, 3:C
2.2.6 HashMap 與 TreeMap 的對(duì)比選擇
| 對(duì)比維度 | HashMap | TreeMap |
|---|---|---|
| 底層結(jié)構(gòu) | 哈希表(數(shù)組 + 鏈表 / 紅黑樹(shù)) | 紅黑樹(shù) |
| 排序特性 | 無(wú)序(按哈希值存儲(chǔ)) | 有序(按鍵的自然 / 自定義順序) |
| 增刪查效率 | 高(O (1),無(wú)哈希沖突時(shí)) | 中(O (log n)) |
| 鍵的 null 支持 | 允許 1 個(gè) null 鍵 | 不允許 null 鍵(會(huì)拋空指針) |
| 線程安全 | 不安全 | 不安全 |
| 適用場(chǎng)景 | 無(wú)需排序,需高效增刪查(如用戶(hù)信息、配置映射) | 需按鍵排序(如按日期的日志、按價(jià)格的商品映射) |
三、不可變集合:線程安全的常量容器
不可變集合是創(chuàng)建后無(wú)法修改的集合(添加、刪除、修改元素會(huì)拋出UnsupportedOperationException),具有線程安全、不可篡改的特性,適用于存儲(chǔ)常量數(shù)據(jù)(如配置參數(shù)、固定枚舉值)或作為公共 API 的返回值(避免外部修改)。
3.1 不可變集合的創(chuàng)建方式
Java 提供 4 種創(chuàng)建不可變集合的方式,各有適用場(chǎng)景:
方式 1:Collections.unmodifiableXXX () —— 不可變視圖(淺拷貝)
通過(guò)Collections工具類(lèi)的unmodifiableList()、unmodifiableSet()、unmodifiableMap()方法,從現(xiàn)有可變集合創(chuàng)建 “不可變視圖”。
- 特點(diǎn):視圖依賴(lài)原集合,原集合修改會(huì)同步影響視圖(淺拷貝),僅限制視圖的修改操作。
- 示例:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class UnmodifiableExample {
public static void main(String[] args) {
// 1. 創(chuàng)建可變集合
List<String> mutableList = new ArrayList<>();
mutableList.add("apple");
// 2. 創(chuàng)建不可變視圖
List<String> immutableList = Collections.unmodifiableList(mutableList);
// 3. 視圖修改會(huì)拋異常
// immutableList.add("banana"); // UnsupportedOperationException
// 4. 原集合修改,視圖會(huì)同步變化(淺拷貝特性)
mutableList.add("banana");
System.out.println(immutableList); // 輸出:[apple, banana]
}
}方式 2:List/Set/Map.of () —— 直接創(chuàng)建不可變集合(深拷貝)

Java 9 + 中,List、Set、Map接口新增of()靜態(tài)方法,可直接傳入元素創(chuàng)建不可變集合,元素不可修改,且不依賴(lài)原集合(深拷貝)。
- 特點(diǎn):
- 元素不可重復(fù)(
Set.of()、Map.of()),重復(fù)會(huì)拋IllegalArgumentException。 Map.of()最多支持 10 個(gè)鍵值對(duì),超過(guò)需用Map.ofEntries()。
- 元素不可重復(fù)(
- 示例:
import java.util.List;
import java.util.Map;
import java.util.Set;
public class ImmutableOfExample {
public static void main(String[] args) {
// 1. 創(chuàng)建不可變List
List<String> immutableList = List.of("apple", "banana", "cherry");
// 2. 創(chuàng)建不可變Set(元素不可重復(fù))
Set<Integer> immutableSet = Set.of(1, 2, 3);
// 3. 創(chuàng)建不可變Map(鍵不可重復(fù),最多10個(gè)鍵值對(duì))
Map<String, Integer> immutableMap = Map.of(
"apple", 1,
"banana", 2,
"cherry", 3
);
// 修改操作均拋異常
// immutableList.add("date"); // UnsupportedOperationException
// immutableSet.remove(1); // UnsupportedOperationException
// immutableMap.put("pear", 4); // UnsupportedOperationException
}
}方式 3:Collectors.toUnmodifiableXXX () —— Stream 流收集(Java 10+)
Java 10 + 中,Collectors工具類(lèi)新增toUnmodifiableList()、toUnmodifiableSet()、toUnmodifiableMap()方法,可將Stream流的結(jié)果收集為不可變集合。
- 示例:
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class ImmutableCollectorExample {
public static void main(String[] args) {
// 將Stream流中的字符串轉(zhuǎn)為大寫(xiě),收集為不可變List
List<String> upperList = Stream.of("apple", "banana", "cherry")
.map(String::toUpperCase)
.collect(Collectors.toUnmodifiableList());
// 修改拋異常
// upperList.add("DATE"); // UnsupportedOperationException
System.out.println(upperList); // 輸出:[APPLE, BANANA, CHERRY]
}
}方式 4:第三方庫(kù)(如 Guava)—— 更靈活的不可變集合
Google 的 Guava 庫(kù)提供了更強(qiáng)大的不可變集合實(shí)現(xiàn)(如ImmutableList、ImmutableMap),支持 Builder 模式,可創(chuàng)建任意長(zhǎng)度的不可變集合,且性能優(yōu)于 JDK 原生方式。
- 依賴(lài)(Maven):
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.1.3-jre</version>
</dependency>import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
public class GuavaImmutableExample {
public static void main(String[] args) {
// 1. 用of()創(chuàng)建不可變List
ImmutableList<String> list = ImmutableList.of("a", "b", "c");
// 2. 用Builder創(chuàng)建不可變Map(支持任意長(zhǎng)度)
ImmutableMap<String, Integer> map = ImmutableMap.<String, Integer>builder()
.put("a", 1)
.put("b", 2)
.put("c", 3)
.build();
// 修改拋異常
// list.add("d"); // UnsupportedOperationException
}
}3.2 不可變集合的核心優(yōu)勢(shì)與適用場(chǎng)景
- 核心優(yōu)勢(shì):
- 線程安全:無(wú)需同步鎖,多線程可安全共享,避免并發(fā)修改問(wèn)題。
- 不可篡改:數(shù)據(jù)創(chuàng)建后無(wú)法修改,保證數(shù)據(jù)一致性(如配置參數(shù)不被意外修改)。
- 性能優(yōu)化:不可變集合無(wú)需預(yù)留擴(kuò)容空間,內(nèi)存占用更小,部分操作(如哈希值)可提前計(jì)算,提升效率。
- 適用場(chǎng)景:
- 存儲(chǔ)固定不變的數(shù)據(jù)(如系統(tǒng)配置、枚舉列表、常量字典)。
- 作為方法返回值(避免外部調(diào)用者修改集合內(nèi)容,保證 API 安全性)。
- 多線程環(huán)境下共享數(shù)據(jù)(無(wú)需額外同步,簡(jiǎn)化代碼)。
四、數(shù)組與集合的對(duì)比總結(jié)
| 對(duì)比維度 | 數(shù)組 | 集合 |
|---|---|---|
| 長(zhǎng)度特性 | 固定長(zhǎng)度,創(chuàng)建后不可修改 | 動(dòng)態(tài)長(zhǎng)度,支持自動(dòng)擴(kuò)容 |
| 元素類(lèi)型 | 支持基本類(lèi)型和引用類(lèi)型 | 僅支持引用類(lèi)型(基本類(lèi)型需用包裝類(lèi)) |
| 內(nèi)存存儲(chǔ) | 連續(xù)內(nèi)存空間 | 非連續(xù)(如 LinkedList、HashSet)或部分連續(xù)(如 ArrayList) |
| 核心方法 | 無(wú)內(nèi)置方法,需手動(dòng)實(shí)現(xiàn)(或用 Arrays 工具類(lèi)) | 內(nèi)置增刪改查方法(add、remove、contains 等) |
| 遍歷方式 | 普通 for 循環(huán)、增強(qiáng) for 循環(huán) | 增強(qiáng) for 循環(huán)、迭代器、forEach(Lambda) |
| 線程安全 | 本身無(wú)線程安全特性,需手動(dòng)同步 | 大部分集合(ArrayList、HashMap)不安全,需用 Concurrent 系列或不可變集合 |
| 適用場(chǎng)景 | 固定長(zhǎng)度、頻繁查詢(xún)(如數(shù)組下標(biāo)訪問(wèn)) | 動(dòng)態(tài)長(zhǎng)度、需頻繁增刪(如購(gòu)物車(chē)、用戶(hù)列表) |
五、知識(shí)擴(kuò)展
5.1 哈希表的工作原理(HashMap/HashSet 底層)
哈希表(Hash Table)是 “數(shù)組 + 鏈表 / 紅黑樹(shù)” 的組合結(jié)構(gòu),核心是通過(guò)哈希函數(shù)將鍵映射到數(shù)組的指定位置(桶),實(shí)現(xiàn)高效的增刪查:
- 哈希函數(shù):通過(guò)鍵的
hashCode()計(jì)算哈希值,再通過(guò) “哈希值 & (數(shù)組長(zhǎng)度 - 1)”(等價(jià)于取模,效率更高)確定桶位置(數(shù)組索引)。 - 哈希沖突:不同鍵計(jì)算出相同桶位置的情況,解決方案:
- 鏈表法:將同一桶中的元素連成鏈表,查詢(xún)時(shí)遍歷鏈表。
- 紅黑樹(shù)法:JDK 8 + 中,當(dāng)鏈表長(zhǎng)度超過(guò) 8 且數(shù)組長(zhǎng)度≥64 時(shí),鏈表轉(zhuǎn)為紅黑樹(shù),將查詢(xún)時(shí)間復(fù)雜度從 O (n) 降至 O (log n)。
- 負(fù)載因子:控制哈希表的 “滿度”,默認(rèn) 0.75,平衡空間與時(shí)間效率:負(fù)載因子過(guò)高會(huì)增加哈希沖突,降低查詢(xún)效率;過(guò)低會(huì)浪費(fèi)內(nèi)存空間。
5.2 紅黑樹(shù)的特性(TreeMap/TreeSet 底層)
紅黑樹(shù)是一種自平衡的二叉搜索樹(shù),通過(guò)以下規(guī)則保證平衡,確保增刪查時(shí)間復(fù)雜度為 O (log n):
- 每個(gè)節(jié)點(diǎn)要么是紅色,要么是黑色。
- 根節(jié)點(diǎn)是黑色。
- 所有葉子節(jié)點(diǎn)(NIL 節(jié)點(diǎn))是黑色。
- 若一個(gè)節(jié)點(diǎn)是紅色,其兩個(gè)子節(jié)點(diǎn)必須是黑色(無(wú)連續(xù)紅色節(jié)點(diǎn))。
- 從任意節(jié)點(diǎn)到其所有葉子節(jié)點(diǎn)的路徑中,黑色節(jié)點(diǎn)的數(shù)量相同(黑高一致)。
- 當(dāng)插入或刪除節(jié)點(diǎn)破壞上述規(guī)則時(shí),紅黑樹(shù)會(huì)通過(guò) “旋轉(zhuǎn)”(左旋、右旋)和 “變色” 調(diào)整,恢復(fù)平衡狀態(tài)。
5.3 自動(dòng)裝箱與拆箱(集合存儲(chǔ)基本類(lèi)型的原理)
集合僅支持引用類(lèi)型,存儲(chǔ)基本類(lèi)型時(shí)需通過(guò) “自動(dòng)裝箱”(基本類(lèi)型→包裝類(lèi))和 “自動(dòng)拆箱”(包裝類(lèi)→基本類(lèi)型)實(shí)現(xiàn),本質(zhì)是編譯器的語(yǔ)法糖:
- 自動(dòng)裝箱:如
list.add(10),編譯器自動(dòng)轉(zhuǎn)為list.add(Integer.valueOf(10)),將int轉(zhuǎn)為Integer。 - 自動(dòng)拆箱:如
int num = list.get(0),編譯器自動(dòng)轉(zhuǎn)為int num = list.get(0).intValue(),將Integer轉(zhuǎn)為int。 - 注意事項(xiàng):避免在循環(huán)中頻繁裝箱(如
for (int i=0; i<1000; i++) list.add(i)),會(huì)創(chuàng)建大量臨時(shí)Integer對(duì)象,建議提前手動(dòng)裝箱或使用基本類(lèi)型集合(如 Eclipse Collections、FastUtil)。
5.4 線程安全的集合類(lèi)
默認(rèn)的集合類(lèi)(如 ArrayList、HashMap、HashSet)均為線程不安全,多線程環(huán)境下需使用線程安全的集合,常用選擇:
- Concurrent 系列:JDK 提供的高效線程安全集合,如
ConcurrentHashMap(HashMap 的線程安全版)、CopyOnWriteArrayList(ArrayList 的線程安全版),通過(guò)分段鎖、寫(xiě)時(shí)復(fù)制等機(jī)制實(shí)現(xiàn)安全,性能優(yōu)于同步集合。 - 同步集合:通過(guò)
Collections.synchronizedXXX()創(chuàng)建,如Collections.synchronizedList(new ArrayList<>()),底層用synchronized關(guān)鍵字加鎖,性能較低(全表鎖),適合并發(fā)量小的場(chǎng)景。 - 不可變集合:如
List.of()、ImmutableList,本身不可修改,天然線程安全,適合存儲(chǔ)常量數(shù)據(jù)。
到此這篇關(guān)于JAVA基礎(chǔ)之?dāng)?shù)組和集合區(qū)別對(duì)比分析的文章就介紹到這了,更多相關(guān)java數(shù)組和集合內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java中的數(shù)組與集合基本用法詳解
- java集合中的迭代器Iterator和數(shù)組內(nèi)置方法及常見(jiàn)的報(bào)錯(cuò)解決方案
- java逗號(hào)分隔String字符串及數(shù)組、集合相互轉(zhuǎn)換
- Java數(shù)組轉(zhuǎn)換為集合的相關(guān)方法
- java與scala數(shù)組及集合的基本操作對(duì)比
- JAVA 區(qū)分集合和數(shù)組
- Java數(shù)組集合的深度復(fù)制代碼實(shí)例
- Java中數(shù)組與集合的相互轉(zhuǎn)換實(shí)現(xiàn)解析
- java集合與數(shù)組的相同點(diǎn)和不同點(diǎn)
相關(guān)文章
詳解Java使用super和this來(lái)重載構(gòu)造方法
這篇文章主要介紹了詳解Java使用super和this來(lái)重載構(gòu)造方法的相關(guān)資料,這里提供實(shí)例來(lái)幫助大家理解這部分內(nèi)容,需要的朋友可以參考下2017-08-08
JAVA音頻處理依賴(lài)庫(kù)示例操作大全(從格式轉(zhuǎn)換到音頻拼接)
在現(xiàn)代應(yīng)用開(kāi)發(fā)中,音頻處理是常見(jiàn)需求,包括格式轉(zhuǎn)換、音頻拼接、剪輯、降噪等操作,本教程將介紹Spring?Boot中常用的音頻處理依賴(lài)庫(kù),比較它們的特性、區(qū)別及社區(qū)活躍程度,并提供實(shí)用代碼示例,感興趣的朋友跟隨小編一起看看吧2025-10-10
Springboot 項(xiàng)目一啟動(dòng)就獲取HttpSession的兩種方法
在SpringBoot項(xiàng)目中,HttpSession是有狀態(tài)的,通常只有在用戶(hù)發(fā)起 HTTP請(qǐng)求并建立會(huì)話后才會(huì)創(chuàng)建,因此,在項(xiàng)目啟動(dòng)時(shí)是無(wú)法獲取到 HttpSession,下面就來(lái)介紹一下Springboot啟動(dòng)就獲取HttpSession,感興趣的可以了解一下2025-10-10

