最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JAVA基礎(chǔ)之?dāng)?shù)組和集合區(qū)別對(duì)比分析

 更新時(shí)間:2025年11月01日 09:56:11   作者:王依華  
文章主要介紹了Java中數(shù)組和集合的基本概念、使用方法以及它們之間的區(qū)別,文章還探討了不可變集合的創(chuàng)建方式及其線程安全和不可篡改的優(yōu)勢(shì),感興趣的朋友跟隨小編一起看看吧

一、數(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。
  • 連續(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ù))返回falseList<String> list = new ArrayList<>(); list.add("Java");
boolean remove(Object o)刪除集合中指定元素,成功返回true,無(wú)此元素返回falselist.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)判斷集合是否包含指定元素,包含返回trueboolean hasJava = list.contains("Java");
boolean isEmpty()判斷集合是否為空(長(zhǎng)度 0),空返回trueboolean 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ù)的單列集合

ListCollection的子接口,特點(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)為 ArrayListSet<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ì)比維度ArrayListLinkedList
底層結(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ù)的單列集合

SetCollection的子接口,特點(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)forforEach。
  • 無(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()方法,具體流程如下:

  1. 調(diào)用新增元素的hashCode()方法,計(jì)算其哈希值,根據(jù)哈希值確定在哈希表中的 “桶位置”(數(shù)組索引)。
  2. 若該桶位置為空,直接將元素存入(無(wú)重復(fù))。
  3. 若該桶位置不為空(哈希沖突),則調(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(減少哈希沖突)。

(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(); // 1
2.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ú)法修改(如StringInteger),或需臨時(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ì)比維度HashSetTreeSet
底層結(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(); // true

2.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ì)集合

HashMapMap最常用的實(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ì)比維度HashMapTreeMap
底層結(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()
  • 示例
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)高效的增刪查:

  1. 哈希函數(shù):通過(guò)鍵的hashCode()計(jì)算哈希值,再通過(guò) “哈希值 & (數(shù)組長(zhǎng)度 - 1)”(等價(jià)于取模,效率更高)確定桶位置(數(shù)組索引)。
  2. 哈希沖突:不同鍵計(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)。
  3. 負(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):

  1. 每個(gè)節(jié)點(diǎn)要么是紅色,要么是黑色。
  2. 根節(jié)點(diǎn)是黑色。
  3. 所有葉子節(jié)點(diǎn)(NIL 節(jié)點(diǎn))是黑色。
  4. 若一個(gè)節(jié)點(diǎn)是紅色,其兩個(gè)子節(jié)點(diǎn)必須是黑色(無(wú)連續(xù)紅色節(jié)點(diǎn))。
  5. 從任意節(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)境下需使用線程安全的集合,常用選擇:

  1. Concurrent 系列:JDK 提供的高效線程安全集合,如ConcurrentHashMap(HashMap 的線程安全版)、CopyOnWriteArrayList(ArrayList 的線程安全版),通過(guò)分段鎖、寫(xiě)時(shí)復(fù)制等機(jī)制實(shí)現(xiàn)安全,性能優(yōu)于同步集合。
  2. 同步集合:通過(guò)Collections.synchronizedXXX()創(chuàng)建,如Collections.synchronizedList(new ArrayList<>()),底層用synchronized關(guān)鍵字加鎖,性能較低(全表鎖),適合并發(fā)量小的場(chǎng)景。
  3. 不可變集合:如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)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java并發(fā)編程示例(十):線程組

    Java并發(fā)編程示例(十):線程組

    這篇文章主要介紹了Java并發(fā)編程示例(十):線程組,Java提供了ThreadGroup類(lèi)來(lái)控制一個(gè)線程組,一個(gè)線程組可以通過(guò)線程對(duì)象來(lái)創(chuàng)建,也可以由其他線程組來(lái)創(chuàng)建,生成一個(gè)樹(shù)形結(jié)構(gòu)的線程,需要的朋友可以參考下
    2014-12-12
  • 詳解Java使用super和this來(lái)重載構(gòu)造方法

    詳解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使用lambda表達(dá)式多條件排序方式

    java使用lambda表達(dá)式多條件排序方式

    這篇文章主要介紹了java使用lambda表達(dá)式多條件排序方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • Spring Boot搭建文件上傳服務(wù)的方法

    Spring Boot搭建文件上傳服務(wù)的方法

    這篇文章主要為大家詳細(xì)介紹了Spring Boot搭建文件上傳服務(wù)的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • Java JDK 1.8 lambda的用法詳解

    Java JDK 1.8 lambda的用法詳解

    這篇文章主要介紹了Java JDK 1.8 lambda的用法詳解,文中給大家提到了jdk 1.8 Lambda 表達(dá)式 遍歷數(shù)組的方法,需要的朋友可以參考下
    2019-09-09
  • Java單例模式繼承覆蓋多態(tài)原理詳解

    Java單例模式繼承覆蓋多態(tài)原理詳解

    這篇文章主要介紹了Java單例模式繼承覆蓋多態(tài)原理詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • JAVA音頻處理依賴(lài)庫(kù)示例操作大全(從格式轉(zhuǎn)換到音頻拼接)

    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
  • java簡(jiǎn)單列出文件夾下所有文件的方法

    java簡(jiǎn)單列出文件夾下所有文件的方法

    這篇文章主要介紹了java簡(jiǎn)單列出文件夾下所有文件的方法,涉及java針對(duì)文件夾遍歷操作相關(guān)技巧,需要的朋友可以參考下
    2016-08-08
  • 淺析JVM逃逸的原理及分析

    淺析JVM逃逸的原理及分析

    在本篇文章里我們給大家分享了JVM逃逸的原理及分析的相關(guān)知識(shí)點(diǎn)內(nèi)容,需要的讀者們可以學(xué)習(xí)下。
    2018-10-10
  • Springboot 項(xiàng)目一啟動(dòng)就獲取HttpSession的兩種方法

    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

最新評(píng)論

抚宁县| 松阳县| 泰和县| 奉新县| 芒康县| 莱西市| 晋宁县| 剑河县| 关岭| 彭泽县| 三门县| 莲花县| 开封市| 徐水县| 高碑店市| 五峰| 方山县| 青浦区| 弋阳县| 湖北省| 鹤山市| 家居| 克山县| 军事| 三门县| 阿鲁科尔沁旗| 香河县| 绥芬河市| 宝丰县| 南川市| 顺义区| 渝中区| 海宁市| 巫溪县| 寿宁县| 安乡县| 当阳市| 水城县| 昌宁县| 马山县| 彭州市|