(十九)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.mzph.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;它们各自有不同的设计目标和优势。下面我综合目前…