Java 容器类详解:架构、实现与使用实践
Java 集合框架中的核心容器类。涵盖 List、Set、Queue 和 Map 四大体系及其常用实现类,如 ArrayList、LinkedList、HashSet、HashMap 等。文章分析了各容器的底层数据结构、时间复杂度、线程安全性及适用场景,并通过代码示例演示了基本操作。此外,还介绍了基本类型与包装类的转换、多线程环境下的并发问题及迭代器的 fail-fast 机制,帮助开发者根据需求选择合适的容器类进行高效开发。

Java 集合框架中的核心容器类。涵盖 List、Set、Queue 和 Map 四大体系及其常用实现类,如 ArrayList、LinkedList、HashSet、HashMap 等。文章分析了各容器的底层数据结构、时间复杂度、线程安全性及适用场景,并通过代码示例演示了基本操作。此外,还介绍了基本类型与包装类的转换、多线程环境下的并发问题及迭代器的 fail-fast 机制,帮助开发者根据需求选择合适的容器类进行高效开发。

| 需求场景 | 推荐容器类 |
|---|---|
| 查询为主,数据量变化小 | ArrayList |
| 增删为主,或需要队列 / 栈 | LinkedList、ArrayDeque |
| 快速去重,不关心顺序 | HashSet |
| 去重且保持插入顺序 | LinkedHashSet |
| 对元素排序 | TreeSet |
| 键值对存储,最常用 | HashMap |
| 键值对保持插入顺序 | LinkedHashMap |
| 对键排序 | TreeMap |
| 多线程环境下的键值对 | ConcurrentHashMap |
Java 容器类是 Java 集合框架(Java Collections Framework)的核心,用于存储和管理一组对象。与数组相比,容器类具有动态扩容、类型安全、操作便捷等优势,是 Java 开发中不可或缺的工具。
Java 容器类主要分为两大体系:Collection 接口和Map 接口,它们是所有容器类的根接口。
List:有序、可重复的集合。Set:无序、不可重复的集合。Queue:队列(先进先出)或双端队列。key-value),键不可重复,值可重复。List 强调元素的'顺序性',每个元素都有对应的索引,可通过索引访问元素。常用实现类有三个:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ArrayListDemo {
public static void main(String[] args) {
// 1. 创建 ArrayList
List<String> list = new ArrayList<>();
// 2. 增:添加元素
list.add("Java");
list.add("Python");
list.add(1, "C++"); // 在指定索引插入
// 3. 删:删除元素
list.remove(0); // 按索引删除
list.remove("Python"); // 按元素删除
// 4. 改:修改元素
list.set(0, "Go");
// 5. 查:获取元素
System.out.println("索引 0 的元素:" + list.get(0));
// 6. 遍历(三种方式)
System.out.println("\n--- 方式 1:普通 for 循环 ---");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
System.out.println("\n--- 方式 2:增强 for 循环 ---");
for (String s : list) {
System.out.println(s);
}
System.out.println("\n--- 方式 3:迭代器(可在遍历中删除) ---");
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
// it.remove(); // 迭代器中安全删除
}
}
}
Deque 接口,可作为双端队列使用。import java.util.LinkedList;
public class LinkedListDemo {
public static void main(String[] args) {
LinkedList<String> linkedList = new LinkedList<>();
// 1. 作为 List 使用(增删改查同 ArrayList)
linkedList.add("A");
linkedList.add("B");
// 2. 作为 队列(FIFO)使用
linkedList.offer("C"); // 入队
System.out.println("队首元素:" + linkedList.peek()); // 查看队首(不删除)
System.out.println("出队:" + linkedList.poll()); // 出队(删除队首)
// 3. 作为 栈(LIFO)使用
linkedList.push("D"); // 入栈
System.out.println("栈顶元素:" + linkedList.peek()); // 查看栈顶
System.out.println("出栈:" + linkedList.pop()); // 出栈(删除栈顶)
System.out.println("最终链表:" + linkedList);
}
}
synchronized 修饰);CopyOnWriteArrayList 替代。Set 强调元素的'唯一性',不允许存储重复元素(通过 equals() 和 hashCode() 方法判断)。常用实现类有三个:
import java.util.HashSet;
import java.util.Set;
public class HashSetDemo {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
// 1. 增:添加元素(重复元素会被自动去重)
set.add("Apple");
set.add("Banana");
set.add("Apple"); // 重复,添加失败
// 2. 删:删除元素
set.remove("Banana");
// 3. 查:判断是否包含
System.out.println("是否包含 Apple:" + set.contains("Apple"));
// 4. 遍历(增强 for 或迭代器,无索引,不能用普通 for)
System.out.println("Set 元素:");
for (String s : set) {
System.out.println(s);
}
}
}
Comparable 或 Comparator 接口实现);import java.util.TreeSet;
public class TreeSetDemo {
public static void main(String[] args) {
// 1. 自然排序(元素需实现 Comparable 接口,如 String、Integer)
TreeSet<Integer> treeSet1 = new TreeSet<>();
treeSet1.add(5);
treeSet1.add(2);
treeSet1.add(8);
System.out.println("自然排序(升序):" + treeSet1); // 输出 [2, 5, 8]
// 2. 定制排序(通过 Comparator 接口指定排序规则)
TreeSet<String> treeSet2 = new TreeSet<>((o1, o2) -> o2.compareTo(o1)); // 降序
treeSet2.add("Banana");
treeSet2.add("Apple");
treeSet2.add("Cherry");
System.out.println("定制排序(降序):" + treeSet2); // 输出 [Cherry, Banana, Apple]
}
}
Queue 用于模拟'队列'数据结构,遵循'先进先出'(FIFO)原则。常用实现类有三个:
Deque 接口,可作为双端队列使用(支持从两端插入 / 删除元素)。import java.util.ArrayDeque;
public class ArrayDequeDemo {
public static void main(String[] args) {
ArrayDeque<String> deque = new ArrayDeque<>();
// 1. 双端队列:两端都可增删
deque.addFirst("A"); // 队首添加
deque.addLast("B"); // 队尾添加
deque.offerFirst("C"); // 队首添加(返回 boolean)
deque.offerLast("D"); // 队尾添加(返回 boolean)
System.out.println("双端队列:" + deque); // 输出 [C, A, B, D]
// 2. 查看元素
System.out.println("队首:" + deque.getFirst()); // 队首(抛异常)
System.out.println("队尾:" + deque.peekLast()); // 队尾(返回 null)
// 3. 删除元素
deque.removeFirst(); // 删除队首(抛异常)
deque.pollLast(); // 删除队尾(返回 null)
System.out.println("删除后:" + deque); // 输出 [A, B]
}
}
Comparator 定制)。import java.util.PriorityQueue;
public class PriorityQueueDemo {
public static void main(String[] args) {
// 1. 默认小顶堆(元素自然排序,最小的在队首)
PriorityQueue<Integer> pq1 = new PriorityQueue<>();
pq1.offer(5);
pq1.offer(2);
pq1.offer(8);
System.out.println("小顶堆出队:");
while (!pq1.isEmpty()) {
System.out.println(pq1.poll()); // 输出 2, 5, 8
}
// 2. 定制大顶堆(通过 Comparator 指定)
PriorityQueue<Integer> pq2 = new PriorityQueue<>((o1, o2) -> o2 - o1);
pq2.offer(5);
pq2.offer(2);
pq2.offer(8);
System.out.println("\n大顶堆出队:");
while (!pq2.isEmpty()) {
System.out.println(pq2.poll()); // 输出 8, 5, 2
}
}
}
Map 用于存储'键值对'(key-value),其中 key 不可重复,value 可重复。常用实现类有四个:
key 和 value 为 null(key 只能有一个 null)。import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class HashMapDemo {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
// 1. 增:添加键值对(Key 重复会覆盖旧 Value)
map.put("Java", 100);
map.put("Python", 90);
map.put("Java", 95); // Key 重复,覆盖 Value 为 95
// 2. 删:删除键值对
map.remove("Python");
// 3. 改:修改 Value(同 put,Key 存在则覆盖)
map.put("Java", 98);
// 4. 查:获取 Value
System.out.println("Java 的分数:" + map.get("Java"));
System.out.println("是否包含 Key:" + map.containsKey("Java"));
System.out.println("是否包含 Value:" + map.containsValue(98));
// 5. 遍历(三种方式)
System.out.println("\n--- 方式 1:遍历 KeySet(获取所有 Key) ---");
Set<String> keys = map.keySet();
for (String key : keys) {
System.out.println(key + " -> " + map.get(key));
}
System.out.println("\n--- 方式 2:遍历 EntrySet(推荐,同时获取 Key 和 Value) ---");
Set<Map.Entry<String, Integer>> entries = map.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
System.out.println(entry.getKey() + " -> " + entry.getValue());
}
System.out.println("\n--- 方式 3:遍历 Values(仅获取所有 Value) ---");
(Integer value : map.values()) {
System.out.println(value);
}
}
}
key 进行自然排序或定制排序);key 不能为 null。key 进行排序的场景。import java.util.TreeMap;
public class TreeMapDemo {
public static void main(String[] args) {
// 1. 自然排序(Key 需实现 Comparable 接口)
TreeMap<Integer, String> treeMap1 = new TreeMap<>();
treeMap1.put(3, "C");
treeMap1.put(1, "A");
treeMap1.put(2, "B");
System.out.println("自然排序(Key 升序):" + treeMap1); // 输出 {1=A, 2=B, 3=C}
// 2. 定制排序(通过 Comparator 指定 Key 排序规则)
TreeMap<Integer, String> treeMap2 = new TreeMap<>((o1, o2) -> o2 - o1); // Key 降序
treeMap2.put(3, "C");
treeMap2.put(1, "A");
treeMap2.put(2, "B");
System.out.println("定制排序(Key 降序):" + treeMap2); // 输出 {3=C, 2=B, 1=A}
}
}
synchronized 修饰);ConcurrentHashMap 替代;key 和 value 都不能为 null。容器类只能存储对象,不能直接存储基本类型(如 int、char)。Java 会通过'自动装箱'将基本类型转换为对应的包装类(如 Integer、Character),反之通过'自动拆箱'转换回基本类型。
大部分常用容器类(如 ArrayList、HashMap、HashSet)都是非线程安全的,在多线程环境下可能出现并发修改异常(ConcurrentModificationException)。若需要线程安全,可选择:
Collections 工具类的同步方法(如 Collections.synchronizedList(new ArrayList<>()));java.util.concurrent 包下的并发容器(如 ConcurrentHashMap、CopyOnWriteArrayList)。容器类的迭代器(Iterator)采用'fail-fast'机制:当迭代过程中容器结构被修改(如增删元素),会立即抛出 ConcurrentModificationException。若需在迭代时修改元素,应使用迭代器的 remove() 方法,而非容器自身的 remove() 方法。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online