API
1. List
1.1 基本API
add(E e):尾部追加add(int index, E e):在指定位置插入,后面的整体右移get(int index):按下标读set(int index, E e):覆盖写,长度不remove(int index)/remove(Object o):一个删位置,一个删值
1 | list.remove(1); // 删的是下标 1 |
size():长度isEmpty():是否为空
1.2 三种遍历方式
- for 下标循环:
可控、最安全,删除时要注意下标回退或倒序遍历。 - 增强 for (
for (E e : list)):
只读视角,禁止结构性修改,否则直接ConcurrentModificationException。 - Iterator:
唯一官方允许的“遍历中删除”方式,用it.remove(),不是list.remove()。
1 | Iterator<Integer> it = list.iterator(); |
1.3 批量操作
addAll(Collection c):拼接removeAll(Collection c):差集retainAll(Collection c):交集containsAll(Collection c):包含关系判断
我认为retainAll特别适合表达“保留合法元素集合”这种语义,比手写循环更不容易出 bug。
1.4 查找相关
contains(Object o):是否存在indexOf(Object o)/lastIndexOf(Object o):第一次 / 最后一次出现的位置
注意一点:这些都是线性扫描,在ArrayList上是 O(n)。如果你在刷题里频繁查存在性,那大概率结构选错了,应该换Set或Map。
1.5 具体实现类
1.5.1 ArrayList
初始化
1 | new ArrayList<>(); |
1.5.2 LinkedList: 双向链表
实现了List<E>, Deque<E>, Queue<E>三个接口, 既能当 List 用,也能当队列、当双端队列用
初始化
1 | //Integer |
作为双端队列:
1 | addFirst(E e) |
offer & poll 和add / remove 的区别不在逻辑,而在失败策略:
add / remove:失败抛异常offer / poll:失败返回false / null
刷题里我建议你统一用offer / poll / peek,更稳。
2. HashMap
3. PriorityQueue<>()
- 初始化
PriorityQueue
pq = new PriorityQueue<>( (a,b)->a-b )
增加元素
pq.offer() 会加入null值的节点, 所以加入时要判断