集合层级(简化)

Iterable
└─ Collection
   ├─ List       有序、可重复(ArrayList / LinkedList)
   ├─ Set        无重复(HashSet / TreeSet)
   └─ Queue      队列(ArrayDeque / PriorityQueue)

Map(不在 Collection 体系)
├─ HashMap
├─ LinkedHashMap
├─ TreeMap
└─ ConcurrentHashMap

List:日常 80%

List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add(0, "x");           // 头插

list.get(0);                 // "x"
list.set(0, "y");            // 改
list.remove(0);              // 按索引删
list.remove("b");            // 按元素删
list.size();                 // 数量
list.contains("a");
list.indexOf("a");
list.isEmpty();

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

ArrayList(动态数组)几乎永远是默认选择。LinkedList 几乎从不用——除了"队列"语义(用 ArrayDeque 也更好)。

Set:去重 + 快速 contains

Set<Integer> set = new HashSet<>();
set.add(1);
set.add(1);                  // 不重复,无操作
set.contains(1);             // O(1)
set.size();                  // 1

// 有序集合
SortedSet<Integer> sorted = new TreeSet<>();
sorted.add(3); sorted.add(1); sorted.add(2);
// 遍历是 1, 2, 3

Map:键值对

Map<String, Integer> ages = new HashMap<>();
ages.put("alice", 30);
ages.put("bob", 25);

ages.get("alice");                   // 30
ages.getOrDefault("nobody", 0);       // 0(不存在时)
ages.containsKey("alice");
ages.containsValue(30);
ages.remove("alice");

// 遍历
for (var entry : ages.entrySet()) {
    System.out.println(entry.getKey() + " = " + entry.getValue());
}

// 只键 / 只值
ages.keySet();
ages.values();

Java 9+ 不可变工厂

List<Integer> list = List.of(1, 2, 3);              // 不可变
Set<String> set = Set.of("a", "b", "c");
Map<String, Integer> map = Map.of("a", 1, "b", 2);

// 大 Map
Map<String, Integer> big = Map.ofEntries(
    Map.entry("a", 1),
    Map.entry("b", 2),
    // ...
);

list.add(4);     // ❌ UnsupportedOperationException

List.of / Set.of / Map.of——不可变不接受 null很简洁。新代码默认用这个。

集合视图:unmodifiable

List<String> mutable = new ArrayList<>();
mutable.add("a");

List<String> readonly = Collections.unmodifiableList(mutable);
readonly.add("b");     // ❌

// 但 mutable 可以改,readonly 也跟着变
mutable.add("b");
System.out.println(readonly);    // [a, b]

返回"只读视图"——底层 list 改了视图也变。要真不可变用 List.ofList.copyOf(mutable)

ArrayDeque:队列 + 栈

// 队列(FIFO)
Deque<Integer> queue = new ArrayDeque<>();
queue.offer(1);
queue.offer(2);
queue.poll();        // 1(取头)
queue.peek();        // 看头不弹

// 栈(LIFO)
Deque<Integer> stack = new ArrayDeque<>();
stack.push(1);
stack.push(2);
stack.pop();         // 2

// 不要用 java.util.Stack——线程同步开销 + 设计有问题

TreeMap / TreeSet:有序

TreeMap<Integer, String> map = new TreeMap<>();
map.put(3, "c");
map.put(1, "a");
map.put(2, "b");

map.firstKey();      // 1
map.lastKey();        // 3
map.headMap(2);       // {1=a}
map.tailMap(2);       // {2=b, 3=c}

红黑树实现,所有操作 O(log n)。需要"按 key 排序遍历"或"范围查询"用。

LinkedHashMap:保持插入顺序

Map<String, Integer> m = new LinkedHashMap<>();
m.put("c", 3); m.put("a", 1); m.put("b", 2);
// 遍历顺序:c, a, b(按插入序)

HashMap 顺序无保证;LinkedHashMap 按插入顺序。

JDK 内部HashMap 在小数据时碰巧有序,但不要依赖——大数据 / rehash 后变。

并发集合

import java.util.concurrent.*;

Map<String, Integer> m = new ConcurrentHashMap<>();   // 多线程友好
List<Integer> list = new CopyOnWriteArrayList<>();     // 读多写少
Queue<Integer> q = new ConcurrentLinkedQueue<>();
BlockingQueue<Integer> bq = new ArrayBlockingQueue<>(10);

多线程时永远用并发集合——不要包 synchronized 自己手写。

数组 vs List

int[] arr = new int[5];                      // 基本类型数组
String[] strs = {"a", "b", "c"};
Integer[] boxed = new Integer[3];            // 包装类数组

// 转换
List<String> list = Arrays.asList(strs);    // 视图(不可变长度)
List<String> mutable = new ArrayList<>(Arrays.asList(strs));   // 可变副本
String[] back = list.toArray(new String[0]);

排序

List<Integer> list = new ArrayList<>(List.of(3, 1, 4, 1, 5));

Collections.sort(list);                                    // 自然顺序
Collections.sort(list, Comparator.reverseOrder());         // 倒序
list.sort(null);                                            // null = 自然顺序

// 自定义
list.sort((a, b) -> b - a);                                 // 简单 lambda
list.sort(Comparator.comparing(String::length));            // 按长度
list.sort(Comparator.comparing(User::getAge)
                    .thenComparing(User::getName));         // 链式

常用工具

Collections.reverse(list);
Collections.shuffle(list);
Collections.frequency(list, "a");
Collections.max(list);
Collections.min(list);
Collections.fill(list, 0);

// java.util.Arrays
Arrays.sort(arr);
Arrays.fill(arr, 0);
Arrays.copyOf(arr, 10);
Arrays.binarySearch(arr, 5);    // 必须先排序
Arrays.toString(arr);            // 打印

Stream 转集合(下一篇细讲

List<Integer> doubled = list.stream()
    .map(n -> n * 2)
    .collect(Collectors.toList());     // 老写法
    // .toList();                       // Java 16+

Set<Integer> set = list.stream().collect(Collectors.toSet());
Map<String, Integer> map = users.stream()
    .collect(Collectors.toMap(User::getName, User::getAge));

实战选择

场景
通用列表 ArrayListList.of(不可变)
去重集合 HashSet
按 key 查 HashMap
保持顺序的 Map LinkedHashMap
按 key 排序 TreeMap
队列 / 栈 ArrayDeque不用 Stack
多线程读写 ConcurrentHashMap
不可变 + 简洁 List.of / Map.of(< 10 元素)

→ 下一篇 Stream API