(十九)Java集合框架深度解析:從基礎到高級應用

一、集合框架概述

1.1 什么是集合框架

Java集合框架(Java Collections Framework, JCF)是Java語言中用于表示和操作集合的一套標準化體系結構。它提供了一組接口、實現類和算法,用于存儲和操作對象組,解決了數組在存儲對象時的諸多限制。

集合框架的主要優勢包括:

  • 減少編程工作量:提供通用的數據結構和算法

  • 提高程序性能:經過優化的實現

  • 促進API互操作性:統一的接口規范

  • 降低學習成本:一致的架構設計

  • 提高軟件質量:經過充分測試的代碼

1.2 集合框架的體系結構

Java集合框架主要由以下幾部分組成:

  1. 接口:定義集合的抽象數據類型

  2. 實現:接口的具體實現類

  3. 算法:對集合進行操作的方法,如排序、搜索等

集合框架的核心接口層次結構如下:

Iterable
└── Collection├── List├── Set│   └── SortedSet└── Queue└── Deque

此外還有獨立的Map接口及其子接口SortedMap

1.3 集合框架的歷史演變

Java集合框架經歷了幾個重要的發展階段:

  • JDK 1.0:只有Vector、Hashtable等簡單集合類

  • JDK 1.2:引入完整的集合框架

  • JDK 1.5:加入泛型支持

  • JDK 1.6:性能優化和小幅API增強

  • JDK 1.7:引入鉆石操作符等語法糖

  • JDK 1.8:加入Stream API和Lambda表達式支持

  • JDK 9:新增不可變集合工廠方法

  • JDK 10:引入var類型推斷

  • JDK 11+:持續優化和增強

二、核心接口詳解

2.1 Collection接口

Collection是集合框架的根接口,定義了所有集合共有的基本操作:

java

public interface Collection<E> extends Iterable<E> {// 基本操作int size();boolean isEmpty();boolean contains(Object element);boolean add(E element);boolean remove(Object element);Iterator<E> iterator();// 批量操作boolean containsAll(Collection<?> c);boolean addAll(Collection<? extends E> c);boolean removeAll(Collection<?> c);boolean retainAll(Collection<?> c);void clear();// 數組操作Object[] toArray();<T> T[] toArray(T[] a);// JDK 8新增的默認方法default boolean removeIf(Predicate<? super E> filter) { ... }default Spliterator<E> spliterator() { ... }default Stream<E> stream() { ... }default Stream<E> parallelStream() { ... }
}

2.2 List接口

List是有序集合(也稱為序列),允許重復元素和null值。主要特點包括:

  • 精確控制每個元素的插入位置

  • 可以通過索引訪問元素

  • 可以搜索元素

  • 允許對列表進行迭代

java

public interface List<E> extends Collection<E> {// 位置訪問操作E get(int index);E set(int index, E element);void add(int index, E element);E remove(int index);int indexOf(Object o);int lastIndexOf(Object o);// 列表迭代器ListIterator<E> listIterator();ListIterator<E> listIterator(int index);// 范圍視圖List<E> subList(int fromIndex, int toIndex);// JDK 8新增的默認方法default void replaceAll(UnaryOperator<E> operator) { ... }default void sort(Comparator<? super E> c) { ... }
}

2.3 Set接口

Set是不包含重復元素的集合,最多包含一個null元素。它模擬了數學上的集合概念,不保證元素的順序(除非使用SortedSet)。

java

public interface Set<E> extends Collection<E> {// 從Collection繼承的方法// JDK 8新增的默認方法default Spliterator<E> spliterator() { ... }
}

2.4 Queue接口

Queue是一種特殊的集合,用于在處理前保存元素。隊列通常(但不一定)以FIFO(先進先出)方式排序元素。

java

public interface Queue<E> extends Collection<E> {// 插入操作boolean add(E e);boolean offer(E e);// 移除操作E remove();E poll();// 檢查操作E element();E peek();
}

2.5 Map接口

Map不是真正的集合(不繼承Collection接口),但完全集成在集合框架中。它將鍵映射到值,鍵不能重復,每個鍵最多映射到一個值。

java

public interface Map<K,V> {// 基本操作int size();boolean isEmpty();boolean containsKey(Object key);boolean containsValue(Object value);V get(Object key);V put(K key, V value);V remove(Object key);void putAll(Map<? extends K, ? extends V> m);void clear();// 集合視圖Set<K> keySet();Collection<V> values();Set<Map.Entry<K, V>> entrySet();// 內部Entry接口interface Entry<K,V> {K getKey();V getValue();V setValue(V value);boolean equals(Object o);int hashCode();// JDK 8新增的默認方法public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K,V>> comparingByKey() { ... }public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K,V>> comparingByValue() { ... }}// JDK 8新增的默認方法default V getOrDefault(Object key, V defaultValue) { ... }default void forEach(BiConsumer<? super K, ? super V> action) { ... }default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) { ... }default V putIfAbsent(K key, V value) { ... }default boolean remove(Object key, Object value) { ... }default boolean replace(K key, V oldValue, V newValue) { ... }default V replace(K key, V value) { ... }default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) { ... }default V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { ... }default V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { ... }default V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) { ... }
}

三、主要實現類分析

3.1 List實現類

3.1.1 ArrayList

基于動態數組的實現,非線程安全。特點:

  • 隨機訪問快(O(1))

  • 尾部插入刪除快(O(1))

  • 中間插入刪除慢(O(n))

  • 內存占用較少

java

// 典型使用場景
List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add(1, "C++"); // 在索引1處插入// 遍歷方式
for (String s : list) {System.out.println(s);
}// JDK 8+的forEach方法
list.forEach(System.out::println);
3.1.2 LinkedList

基于雙向鏈表的實現,同時實現了List和Deque接口。特點:

  • 任意位置插入刪除快(O(1))

  • 隨機訪問慢(O(n))

  • 內存占用較多(需要存儲前后節點引用)

java

// 典型使用場景
List<Integer> linkedList = new LinkedList<>();
linkedList.add(10);
linkedList.addFirst(5); // 作為Deque使用
linkedList.addLast(15); // 作為Deque使用// 迭代器遍歷
Iterator<Integer> it = linkedList.iterator();
while (it.hasNext()) {System.out.println(it.next());
}
3.1.3 Vector

線程安全的動態數組實現,方法都使用synchronized修飾。已逐漸被ArrayList和Collections.synchronizedList取代。

java

// 使用示例
Vector<String> vector = new Vector<>();
vector.add("Old");
vector.add("Collection");
3.1.4 CopyOnWriteArrayList

線程安全的List實現,適合讀多寫少的場景。所有修改操作都會創建底層數組的新副本。

java

// 使用示例
CopyOnWriteArrayList<String> cowList = new CopyOnWriteArrayList<>();
cowList.add("Thread-safe");
cowList.add("List");

3.2 Set實現類

3.2.1 HashSet

基于HashMap實現的Set,使用對象的hashCode()方法確定元素位置。特點:

  • 元素無序

  • 添加、刪除、包含操作都是O(1)

  • 允許null元素

java

// 使用示例
Set<String> set = new HashSet<>();
set.add("Apple");
set.add("Banana");
set.add("Apple"); // 重復元素不會被添加System.out.println(set.contains("Apple")); // true
3.2.2 LinkedHashSet

繼承自HashSet,但同時維護了一個雙向鏈表來保持插入順序。特點:

  • 迭代順序可預測

  • 性能略低于HashSet

  • 適合需要保持插入順序的場景

java

// 使用示例
Set<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add("First");
linkedHashSet.add("Second");
linkedHashSet.add("Third");// 遍歷時會按照插入順序輸出
linkedHashSet.forEach(System.out::println);
3.2.3 TreeSet

基于TreeMap實現的NavigableSet,元素按照自然順序或Comparator排序。特點:

  • 元素有序

  • 添加、刪除、包含操作都是O(log n)

  • 不允許null元素(除非Comparator允許)

java

// 使用示例
Set<Integer> treeSet = new TreeSet<>();
treeSet.add(5);
treeSet.add(2);
treeSet.add(8);// 遍歷時會按照自然順序輸出
treeSet.forEach(System.out::println); // 輸出 2,5,8
3.2.4 CopyOnWriteArraySet

基于CopyOnWriteArrayList實現的線程安全Set,適合讀多寫少的場景。

java

// 使用示例
CopyOnWriteArraySet<String> cowSet = new CopyOnWriteArraySet<>();
cowSet.add("Thread-safe");
cowSet.add("Set");
3.2.5 EnumSet

專為枚舉類型設計的高性能Set實現,內部使用位向量表示。

java

// 使用示例
enum Day { MONDAY, TUESDAY, WEDNESDAY }
EnumSet<Day> days = EnumSet.of(Day.MONDAY, Day.WEDNESDAY);

3.3 Queue實現類

3.3.1 LinkedList

如前所述,LinkedList也實現了Deque接口,因此可以作為隊列使用。

java

// 作為隊列使用
Queue<String> queue = new LinkedList<>();
queue.offer("First");
queue.offer("Second");
String first = queue.poll(); // 移除并返回頭部元素
3.3.2 PriorityQueue

基于優先級堆的無界優先級隊列,元素按照自然順序或Comparator排序。

java

// 使用示例
Queue<Integer> priorityQueue = new PriorityQueue<>();
priorityQueue.offer(5);
priorityQueue.offer(1);
priorityQueue.offer(3);// 出隊順序是1,3,5
while (!priorityQueue.isEmpty()) {System.out.println(priorityQueue.poll());
}
3.3.3 ArrayDeque

基于循環數組實現的雙端隊列,比LinkedList更高效。適合用作棧或隊列。

java

// 作為棧使用
Deque<String> stack = new ArrayDeque<>();
stack.push("First");
stack.push("Second");
String top = stack.pop(); // "Second"// 作為隊列使用
Deque<String> queue = new ArrayDeque<>();
queue.offer("First");
queue.offer("Second");
String first = queue.poll(); // "First"
3.3.4 BlockingQueue實現

java.util.concurrent包提供了多種阻塞隊列實現:

  • ArrayBlockingQueue:有界阻塞隊列

  • LinkedBlockingQueue:可選有界阻塞隊列

  • PriorityBlockingQueue:無界優先級阻塞隊列

  • SynchronousQueue:不存儲元素的阻塞隊列

  • DelayQueue:元素延遲到期的無界阻塞隊列

java

// 使用示例
BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(10);
// 生產者線程
new Thread(() -> {try {blockingQueue.put("Message");} catch (InterruptedException e) {Thread.currentThread().interrupt();}
}).start();// 消費者線程
new Thread(() -> {try {String message = blockingQueue.take();System.out.println("Received: " + message);} catch (InterruptedException e) {Thread.currentThread().interrupt();}
}).start();

3.4 Map實現類

3.4.1 HashMap

基于哈希表的Map實現,允許null鍵和null值。特點:

  • 鍵無序

  • 基本操作時間復雜度為O(1)

  • 初始容量和負載因子影響性能

java

// 使用示例
Map<String, Integer> map = new HashMap<>();
map.put("Alice", 25);
map.put("Bob", 30);
map.put("Charlie", 28);// 獲取值
int age = map.get("Bob"); // 30// 遍歷
map.forEach((name, age) -> System.out.println(name + " is " + age + " years old"));
3.4.2 LinkedHashMap

繼承自HashMap,同時維護了一個雙向鏈表來保持插入順序或訪問順序。特點:

  • 可以預測的迭代順序

  • 性能略低于HashMap

  • 適合需要保持插入/訪問順序的場景

java

// 保持插入順序
Map<String, Integer> linkedMap = new LinkedHashMap<>();
linkedMap.put("First", 1);
linkedMap.put("Second", 2);
linkedMap.put("Third", 3);// 遍歷順序與插入順序一致
linkedMap.forEach((k, v) -> System.out.println(k));// 創建LRU緩存
Map<String, Integer> lruCache = new LinkedHashMap<>(16, 0.75f, true) {@Overrideprotected boolean removeEldestEntry(Map.Entry<String, Integer> eldest) {return size() > 3;}
};
3.4.3 TreeMap

基于紅黑樹實現的NavigableMap,鍵按照自然順序或Comparator排序。特點:

  • 鍵有序

  • 基本操作時間復雜度為O(log n)

  • 不允許null鍵(除非Comparator允許)

java

// 使用示例
Map<String, Integer> treeMap = new TreeMap<>();
treeMap.put("Orange", 2);
treeMap.put("Apple", 5);
treeMap.put("Banana", 3);// 遍歷順序是Apple, Banana, Orange
treeMap.forEach((fruit, count) -> System.out.println(fruit + ": " + count));
3.4.4 Hashtable

線程安全的Map實現,方法都使用synchronized修飾。已逐漸被HashMap和ConcurrentHashMap取代。

java

// 使用示例
Hashtable<String, Integer> table = new Hashtable<>();
table.put("One", 1);
table.put("Two", 2);
3.4.5 ConcurrentHashMap

線程安全的高性能HashMap實現,使用分段鎖技術(JDK 8后改為CAS+synchronized)。特點:

  • 高并發性能

  • 不允許null鍵和null值

  • 操作通常不需要鎖定整個表

java

// 使用示例
ConcurrentMap<String, Integer> concurrentMap = new ConcurrentHashMap<>();
concurrentMap.put("Key1", 1);
concurrentMap.putIfAbsent("Key1", 2); // 不會替換已有值// 原子更新
concurrentMap.compute("Key1", (k, v) -> v == null ? 0 : v + 1);
3.4.6 EnumMap

專為枚舉鍵設計的Map實現,內部使用數組存儲,非常緊湊和高效。

java

// 使用示例
enum Day { MONDAY, TUESDAY, WEDNESDAY }
Map<Day, String> enumMap = new EnumMap<>(Day.class);
enumMap.put(Day.MONDAY, "First day");
3.4.7 IdentityHashMap

使用==而不是equals比較鍵的Map實現,適合需要對象標識而非對象值相等的場景。

java

// 使用示例
Map<String, Integer> identityMap = new IdentityHashMap<>();
String key1 = new String("key");
String key2 = new String("key");
identityMap.put(key1, 1);
identityMap.put(key2, 2); // 兩個不同的鍵
System.out.println(identityMap.size()); // 2
3.4.8 WeakHashMap

使用弱引用作為鍵的Map實現,當鍵不再被普通引用時,條目會被自動移除。適合實現緩存。

java

// 使用示例
Map<Object, String> weakMap = new WeakHashMap<>();
Object key = new Object();
weakMap.put(key, "value");
key = null; // 使鍵只被弱引用持有
System.gc(); // 垃圾回收后,條目可能會被移除

四、集合工具類

4.1 Collections工具類

java.util.Collections提供了大量靜態方法,用于操作或返回集合。

4.1.1 排序和搜索

java

List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5, 9);// 排序
Collections.sort(numbers); // [1, 1, 3, 4, 5, 9]// 自定義排序
Collections.sort(numbers, Comparator.reverseOrder()); // [9, 5, 4, 3, 1, 1]// 二分查找(列表必須已排序)
int index = Collections.binarySearch(numbers, 4); // 2// 隨機打亂
Collections.shuffle(numbers);
4.1.2 不可變集合

java

// 創建不可變集合
List<String> immutableList = Collections.unmodifiableList(new ArrayList<>());
Set<Integer> immutableSet = Collections.unmodifiableSet(new HashSet<>());
Map<String, Integer> immutableMap = Collections.unmodifiableMap(new HashMap<>());// JDK 9新增的工廠方法
List<String> list = List.of("a", "b", "c");
Set<Integer> set = Set.of(1, 2, 3);
Map<String, Integer> map = Map.of("a", 1, "b", 2);
4.1.3 同步集合

java

// 創建線程安全集合
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
Set<Integer> syncSet = Collections.synchronizedSet(new HashSet<>());
Map<String, Integer> syncMap = Collections.synchronizedMap(new HashMap<>());
4.1.4 其他實用方法

java

// 填充
List<String> list = new ArrayList<>(Collections.nCopies(3, "default"));
Collections.fill(list, "new"); // ["new", "new", "new"]// 頻率統計
int freq = Collections.frequency(list, "new"); // 3// 極值
Integer max = Collections.max(numbers);
Integer min = Collections.min(numbers);// 替換所有
Collections.replaceAll(list, "new", "old");// 反轉
Collections.reverse(list);// 旋轉(將后兩個元素移到前面)
Collections.rotate(list, 2);

4.2 Arrays工具類

java.util.Arrays提供了操作數組的實用方法,許多方法與Collections類似。

java

// 數組轉List(返回的List是固定大小的)
List<String> list = Arrays.asList("a", "b", "c");// 排序
int[] numbers = {3, 1, 4, 1, 5, 9};
Arrays.sort(numbers); // [1, 1, 3, 4, 5, 9]// 二分查找
int index = Arrays.binarySearch(numbers, 4); // 3// 填充
Arrays.fill(numbers, 0); // [0, 0, 0, 0, 0, 0]// 比較
int[] copy = Arrays.copyOf(numbers, numbers.length);
boolean equal = Arrays.equals(numbers, copy); // true// 字符串表示
String str = Arrays.toString(numbers); // "[0, 0, 0, 0, 0, 0]"// 并行排序(大數據量時性能更好)
Arrays.parallelSort(new int[] {5, 3, 9, 1});// JDK 8新增的Stream支持
int sum = Arrays.stream(numbers).sum();

五、集合的迭代與遍歷

5.1 迭代器模式

Java集合框架基于迭代器模式,提供了一種統一的方法來遍歷各種集合。

5.1.1 Iterator接口

java

public interface Iterator<E> {boolean hasNext();E next();default void remove() { throw new UnsupportedOperationException(); }default void forEachRemaining(Consumer<? super E> action) { ... }
}

基本用法:

java

List<String> list = Arrays.asList("A", "B", "C");
Iterator<String> it = list.iterator();
while (it.hasNext()) {String element = it.next();System.out.println(element);if (element.equals("B")) {it.remove(); // 移除當前元素}
}
5.1.2 ListIterator接口

ListIterator擴展了Iterator,支持雙向遍歷和修改操作。

java

public interface ListIterator<E> extends Iterator<E> {boolean hasNext();E next();boolean hasPrevious();E previous();int nextIndex();int previousIndex();void remove();void set(E e);void add(E e);
}

使用示例:

java

List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
ListIterator<String> lit = list.listIterator();// 正向遍歷
while (lit.hasNext()) {System.out.println(lit.next());
}// 反向遍歷
while (lit.hasPrevious()) {String element = lit.previous();System.out.println(element);if (element.equals("B")) {lit.set("B-Updated"); // 修改當前元素}
}
5.1.3 快速失敗(fail-fast)機制

大多數集合的迭代器實現了快速失敗機制,當在迭代過程中檢測到集合被修改(除了通過迭代器自己的remove方法),會拋出ConcurrentModificationException

java

List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));// 會拋出ConcurrentModificationException
for (String s : list) {if (s.equals("B")) {list.remove(s); // 錯誤的方式}
}// 正確的修改方式
Iterator<String> it = list.iterator();
while (it.hasNext()) {if (it.next().equals("B")) {it.remove(); // 通過迭代器移除}
}

5.2 遍歷集合的各種方式

5.2.1 傳統的for循環(適合List)

java

List<String> list = Arrays.asList("A", "B", "C");
for (int i = 0; i < list.size(); i++) {System.out.println(list.get(i));
}
5.2.2 增強的for-each循環

java

for (String s : list) {System.out.println(s);
}
5.2.3 使用Iterator

java

Iterator<String> it = list.iterator();
while (it.hasNext()) {System.out.println(it.next());
}
5.2.4 使用ListIterator

java

ListIterator<String> lit = list.listIterator();
while (lit.hasNext()) {System.out.println(lit.next());
}
5.2.5 使用Java 8的forEach方法

java

list.forEach(System.out::println);// 或使用Lambda表達式
list.forEach(s -> System.out.println(s));
5.2.6 使用Stream API

java

list.stream().forEach(System.out::println);// 并行處理
list.parallelStream().forEach(System.out::println);

5.3 Spliterator接口

JDK 8引入的Spliterator(可分迭代器)用于并行遍歷和分割元素序列。

java

public interface Spliterator<T> {boolean tryAdvance(Consumer<? super T> action);Spliterator<T> trySplit();long estimateSize();int characteristics();
}

使用示例:

java

List<String> list = Arrays.asList("A", "B", "C", "D", "E");
Spliterator<String> spliterator = list.spliterator();// 嘗試分割
Spliterator<String> half = spliterator.trySplit();// 處理前半部分
half.forEachRemaining(System.out::println); // 輸出 A, B// 處理后半部分
spliterator.forEachRemaining(System.out::println); // 輸出 C, D, E

六、集合的性能比較與選擇

6.1 主要集合類的性能特征

集合類型實現類獲取插入/刪除包含有序線程安全允許null
ListArrayListO(1)O(n)O(n)插入順序
ListLinkedListO(n)O(1)O(n)插入順序
ListVectorO(1)O(n)O(n)插入順序
SetHashSetO(1)O(1)O(1)是(1個)
SetLinkedHashSetO(1)O(1)O(1)插入順序是(1個)
SetTreeSetO(log n)O(log n)O(log n)排序順序
QueuePriorityQueueO(1) peekO(log n) offer-排序順序
MapHashMapO(1)O(1)O(1)是(1個鍵)
MapLinkedHashMapO(1)O(1)O(1)插入/訪問順序是(1個鍵)
MapTreeMapO(log n)O(log n)O(log n)排序順序否(鍵)
MapHashtableO(1)O(1)O(1)
MapConcurrentHashMapO(1)O(1)O(1)

6.2 如何選擇合適的集合

選擇集合時應考慮以下因素:

  1. 元素是否需要有序

    • 需要保持插入順序:LinkedHashSet、LinkedHashMap、ArrayList、LinkedList

    • 需要排序:TreeSet、TreeMap、PriorityQueue

    • 不需要順序:HashSet、HashMap

  2. 是否需要允許重復元素

    • 允許重復:List及其實現類

    • 不允許重復:Set及其實現類

  3. 性能需求

    • 隨機訪問多:ArrayList

    • 插入刪除多:LinkedList

    • 快速查找:HashSet/HashMap

  4. 線程安全需求

    • 需要線程安全:ConcurrentHashMap、CopyOnWriteArrayList、Collections.synchronizedXxx

    • 不需要線程安全:標準實現類

  5. null值處理

    • 需要存儲null:ArrayList、HashSet、HashMap等

    • 不能存儲null:Hashtable、ConcurrentHashMap、EnumSet/Map等

  6. 內存占用

    • 內存敏感:ArrayList比LinkedList更節省空間

    • EnumSet/Map非常緊湊高效

6.3 集合初始容量與負載因子

對于基于哈希表的集合(HashMap、HashSet等),初始容量和負載因子影響性能:

  • 初始容量:哈希表創建時的桶數量。默認16。

  • 負載因子:哈希表自動擴容前的填充比例。默認0.75。

java

// 自定義初始容量和負載因子
Map<String, Integer> map = new HashMap<>(32, 0.5f);

合理設置這些參數可以減少rehash操作,提高性能:

  • 如果知道元素數量,設置初始容量為預期數量的1.33倍(1/0.75)

  • 高負載因子減少內存使用但增加查找成本

  • 低負載因子提高查找性能但增加內存使用

七、Java 8/9/10對集合的增強

7.1 Java 8的增強

7.1.1 Stream API

Stream API為集合提供了強大的數據操作能力:

java

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");// 過濾和映射
List<String> result = names.stream().filter(name -> name.length() > 4).map(String::toUpperCase).collect(Collectors.toList());// 統計
long count = names.stream().filter(name -> name.startsWith("A")).count();// 并行處理
int totalLength = names.parallelStream().mapToInt(String::length).sum();
7.1.2 forEach方法

所有集合都新增了forEach方法:

java

Map<String, Integer> map = new HashMap<>();
map.put("A", 1);
map.put("B", 2);// 遍歷Map
map.forEach((k, v) -> System.out.println(k + "=" + v));
7.1.3 Map的增強方法

Map接口新增了許多實用方法:

java

Map<String, Integer> map = new HashMap<>();// 鍵不存在時才放入
map.putIfAbsent("A", 1);// 根據鍵計算新值
map.compute("A", (k, v) -> v == null ? 0 : v + 1);// 合并值
map.merge("A", 1, (oldVal, newVal) -> oldVal + newVal);// 獲取或默認值
int val = map.getOrDefault("B", 0);
7.1.4 Collection的removeIf方法

java

List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));// 移除所有偶數
numbers.removeIf(n -> n % 2 == 0); // [1, 3, 5]

7.2 Java 9的增強

7.2.1 不可變集合的工廠方法

Java 9引入了簡潔的創建不可變集合的方法:

java

// 不可變List
List<String> immutableList = List.of("a", "b", "c");// 不可變Set
Set<Integer> immutableSet = Set.of(1, 2, 3);// 不可變Map
Map<String, Integer> immutableMap = Map.of("a", 1, "b", 2);// 更多元素的Map
Map<String, Integer> map = Map.ofEntries(Map.entry("a", 1),Map.entry("b", 2),Map.entry("c", 3)
);

這些集合:

  • 不允許null元素

  • 創建后不可修改

  • 空間優化(可能使用專用內部類)

7.2.2 其他增強
  • Optional增加了stream()方法

  • 新增Collectors.filteringCollectors.flatMapping

7.3 Java 10的增強

7.3.1 不可變集合的copyOf方法

java

List<String> original = new ArrayList<>();
List<String> copy = List.copyOf(original); // 不可變副本
7.3.2 var關鍵字與集合

雖然var不是集合特有的,但它簡化了集合聲明:

java

var list = new ArrayList<String>(); // 推斷為ArrayList<String>
var map = new HashMap<Integer, String>(); // 推斷為HashMap<Integer, String>

八、集合的最佳實踐

8.1 通用最佳實踐

  1. 使用接口類型聲明集合

    java

    // 好
    List<String> list = new ArrayList<>();
    // 不好
    ArrayList<String> list = new ArrayList<>();

  2. 預估集合大小

    java

    // 如果知道大約需要存儲1000個元素
    List<String> list = new ArrayList<>(1000);

  3. 使用isEmpty()而不是size()==0

    java

    // 好
    if (list.isEmpty()) { ... }
    // 不好
    if (list.size() == 0) { ... }

  4. 優先使用for-each循環

    java

    for (String s : list) { ... }

  5. 注意集合的equals和hashCode

    • 不同集合類的equals行為不同

    • 修改作為Map鍵的對象時要小心

8.2 并發場景下的最佳實踐

  1. 選擇合適的并發集合

    • 高并發讀取:ConcurrentHashMap

    • 寫少讀多:CopyOnWriteArrayList

    • 阻塞隊列:ArrayBlockingQueue

  2. 避免在迭代時修改集合

    • 使用并發集合或同步塊

    • 或者先創建副本再迭代

  3. 注意原子復合操作

    java

    // 非原子操作
    if (!map.containsKey(key)) {map.put(key, value);
    }// 使用原子方法
    map.putIfAbsent(key, value);

8.3 性能優化建議

  1. 選擇合適的集合類型

    • 隨機訪問多:ArrayList

    • 插入刪除多:LinkedList

  2. 合理設置HashMap/HashSet初始容量

    java

    // 預期存儲1000個元素,負載因子0.75
    Map<String, Integer> map = new HashMap<>(1333); // 1000 / 0.75

  3. 考慮使用EnumSet/EnumMap

    • 枚舉集合非常高效

  4. 避免頻繁的裝箱拆箱

    • 考慮使用Trove、FastUtil等第三方庫

  5. 批量操作優于單元素操作

    java

    // 好
    list.addAll(otherList);
    // 不好
    for (String s : otherList) {list.add(s);
    }

8.4 常見陷阱與避免方法

  1. ConcurrentModificationException

    • 避免在迭代時直接修改集合

    • 使用迭代器的remove方法或并發集合

  2. 可變對象作為Map鍵

    • 如果鍵對象可變,修改后可能導致找不到值

    • 建議使用不可變對象作為鍵

  3. equals和hashCode不一致

    • 確保相等的對象有相同的hashCode

    • 重寫equals時必須重寫hashCode

  4. 原始集合的泛型使用

    • 避免使用原始類型集合

    • 總是指定泛型參數

  5. 內存泄漏

    • 長期存活的集合可能導致內存泄漏

    • 考慮使用WeakHashMap或定期清理

九、集合框架的擴展與替代方案

9.1 第三方集合庫

9.1.1 Google Guava

Google的Guava庫提供了豐富的集合工具:

java

// 不可變集合
ImmutableList<String> immutableList = ImmutableList.of("a", "b", "c");// 多值Map
Multimap<String, Integer> multimap = ArrayListMultimap.create();
multimap.put

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

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

相關文章

Blender cycles烘焙貼圖筆記

下載了一些槍模型&#xff0c;一個模型有七八個材質&#xff0c;一個扳機、準星還有單獨的材質&#xff0c;用的貼圖只有一小部分有內容&#xff0c;對Draw Call非常不友好。不得不學一下怎么用Blender減材質。 找到了這個視頻如何在Blender中將多種材料多張貼圖烘焙成一張貼圖…

mysql的高可用

1. 環境準備 2臺MySQL服務器&#xff08;node1: 192.168.1.101&#xff0c;node2: 192.168.1.102&#xff09;2臺HAProxy Keepalived服務器&#xff08;haproxy1: 192.168.1.103&#xff0c;haproxy2: 192.168.1.104&#xff09;虛擬IP&#xff08;VIP: 192.168.1.100&#x…

鴻蒙 系統-安全-程序訪問控制-應用權限管控

Ability Kit 提供了一種允許應用訪問系統資源&#xff08;如&#xff1a;通訊錄等&#xff09;和系統能力&#xff08;如&#xff1a;訪問攝像頭、麥克風等&#xff09;的通用權限訪問方式&#xff0c;來保護系統數據&#xff08;包括用戶個人數據&#xff09;或功能&#xff0…

算法-數對的使用

1、數對可用于數組排序中&#xff0c;并且可記憶化排序前的元素下標 #include<iostream> #include<string> #include<bits/stdc.h> using namespace std; typedef long long ll; const int N 2e5 10; pair<int, int> a[N]; void solve() {ll n;cin …

Linux基礎第四天

系統之間文件共享 想要實現兩個不同的系統之間實現文件共享&#xff0c;最簡單的一種方案就是設置VMware軟件的共享文件夾&#xff0c;利用共享文件夾可以實現linux系統和windows系統之間的文件共享&#xff0c;這樣就可以實現在windows系統上編輯程序&#xff0c;然后在linux系…

Docker 核心原理詳解:Namespaces 與 Cgroups 如何實現資源隔離與限制

#Docker疑難雜癥解決指南# Docker 作為容器化技術的代名詞,徹底改變了軟件的開發、部署和管理方式。它憑借其輕量、快速、一致性強的特性,成為了現代云原生架構的基石。然而,Docker 容器的神奇之處并非“無中生有”,其背后是 Linux 內核的兩大核心技術——Namespaces(命名…

GitHub 趨勢日報 (2025年05月14日)

本日報由 TrendForge 系統生成 https://trendforge.devlive.org/ &#x1f310; 本日報中的項目描述已自動翻譯為中文 &#x1f4c8; 今日整體趨勢 Top 10 排名項目名稱項目描述今日獲星總星數語言1xming521/WeClone&#x1f680;從聊天記錄創造數字分身的一站式解決方案&…

【Go】從0開始學習Go

文章目錄 從0開始學習Go0 與C對比1 代碼框架1.1 helloworld式代碼示例1.2 主體代碼元素&#xff08;核心三部分&#xff09;1.3 其他 2 與C/C區別3 有用的小工具4 注意事項 從0開始學習Go 0 與C對比 特性CGo編譯型語言需要編譯為機器碼直接編譯為二進制可執行文件靜態類型類型…

簡單說一下 Webpack分包

最近在看有關webpack分包的知識&#xff0c;搜索了很多資料&#xff0c;感覺這一塊很是迷惑&#xff0c;網上的資料講的也迷迷糊糊&#xff0c;這里簡單總結分享一下&#xff0c;也當個筆記。 如有錯誤請指出。 為什么需要分包 我們知道&#xff0c;webpack的作用&#xff0c…

使用Python和FastAPI構建網站爬蟲:Oncolo醫療文章抓取實戰

使用Python和FastAPI構建網站爬蟲&#xff1a;Oncolo醫療文章抓取實戰 前言項目概述技術棧代碼分析1. 導入必要的庫2. 初始化FastAPI應用3. 定義請求模型4. 核心爬蟲功能4.1 URL驗證和準備4.2 設置HTTP請求4.3 發送請求和解析HTML4.4 提取文章內容4.5 保存結果和返回數據 5. AP…

YoloV8改進策略:卷積篇|風車卷積|即插即用

文章目錄 論文信息論文翻譯摘要引言相關研究紅外搜索與跟蹤檢測和分割網絡紅外搜索與跟蹤數據集的損失函數紅外搜索與跟蹤數據集方法風車形卷積(PConv)基于尺度的動態損失SIRST - UAVB數據集實驗實驗設置與其他方法的比較多模型上的消融實驗結論致謝代碼改進方法測試結果總結…

【NLP】36. 從指令微調到人類偏好:構建更有用的大語言模型

從指令微調到人類偏好&#xff1a;構建更有用的大語言模型 大語言模型&#xff08;LLMs&#xff09;已經成為現代自然語言處理系統的核心&#xff0c;但單純依賴傳統語言建模目標&#xff0c;往往難以滿足實際應用的“人類意圖”。從 Instruction Tuning&#xff08;指令微調&…

基于Transformers與深度學習的微博評論情感分析及AI自動回復系統

前言 這個項目存在cookie沒有自動更新問題&#xff0c;后續可能會發出來解決教程&#xff0c;還有微博網頁版的話最多看到300條評論&#xff0c;而且回復別人信息的話最多回復15條就要休息5分鐘左右才能評論 1. 項目概述 本項目實現了一個微博評論自動化處理系統&#xff0c…

詳解 Zephyr RTOS:架構、功能與開發指南

目錄 Zephyr RTOS 的核心特性 1. 輕量級和可擴展性 2. 實時性能 3. 多平臺支持 4. 安全性 5. 社區和生態系統 Zephyr 的架構 1. 內核 2. 驅動模型 3. 網絡棧 4. 文件系統 開發環境和工具鏈 安裝和配置 開發流程 1. 應用程序開發 2. 調試和測試 3. 部署 實際應…

人工智能重塑醫療健康:從輔助診斷到個性化治療的全方位變革

人工智能正在以前所未有的速度改變著醫療健康領域&#xff0c;從影像診斷到藥物研發&#xff0c;從醫院管理到遠程醫療&#xff0c;AI 技術已滲透到醫療服務的各個環節。本文將深入探討人工智能如何賦能醫療健康產業&#xff0c;分析其在醫學影像、臨床決策、藥物研發、個性化醫…

Linux筆記---內核態與用戶態

用戶態&#xff08;User Mode&#xff09; 權限級別&#xff1a;較低&#xff0c;限制應用程序直接訪問硬件或關鍵系統資源。 適用場景&#xff1a;普通應用程序的運行環境。 限制&#xff1a;無法執行特權指令&#xff08;如操作I/O端口、修改內存管理單元配置等&#xff09…

Spring 代理與 Redis 分布式鎖沖突:一次鎖釋放異常的分析與解決

Spring 代理與 Redis 分布式鎖沖突&#xff1a;一次鎖釋放異常的分析與解決 Spring 代理與 Redis 分布式鎖沖突&#xff1a;一次鎖釋放異常的分析與解決1. 問題現象與初步分析2 . 原因探究&#xff1a;代理機制對分布式鎖生命周期的干擾3. 問題復現偽代碼4. 解決方案&#xff1…

SQL:多列匹配(Multiple-column Matching)

目錄 基礎概念 應用場景詳解 1. 多列等值匹配 2. 多列 IN 匹配&#xff08;集合匹配&#xff09; 3. 多列 JOIN 匹配&#xff08;復合鍵連接&#xff09; 4. 多列匹配 子查詢 5. 多列匹配 EXISTS 6. 多列匹配 UNION&#xff08;組合數據源&#xff09; 7. 多列匹配…

基于DeepSeek的智能客服系統實踐與創新

引言:AI大模型重塑客戶服務新范式 近年來,AI大模型技術的突破性進展正在深刻改變傳統客戶服務模式。作為國內領先的AI企業,DeepSeek憑借其創新的算法架構(如MoE混合專家模型、動態學習率調度器)和極致的成本效益(僅為同類模型成本的1/20),在自然語言理解、情感分析、多…

SGLang和vllm比有什么優勢?

環境&#xff1a; SGLang vllm 問題描述&#xff1a; SGLang和vllm比有什么優勢&#xff1f; 解決方案&#xff1a; SGLang和vLLM都是在大語言模型&#xff08;LLM&#xff09;推理和部署領域的開源項目或框架&#xff0c;它們各自有不同的設計目標和優勢。下面我綜合目前…