clear() 是最直接且安全的清空方式,它移除所有元素、保持对象引用不变、语义明确、性能可控,而 new XXX() 易致内存泄漏,removeAll()/retainAll() 效率低且非原子,Map 清空也应优先用 clear()。

clear() 是最直接且安全的清空方式
Java 集合接口(Collection 及其子接口如 List、Set、Queue)都定义了 clear() 方法,它会移除所有元素,将集合大小归零,同时保持集合对象本身不变。
这是推荐做法,因为:
- 语义明确:意图就是清空,不是重建或替换
- 性能可控:多数实现(如
ArrayList、HashSet)是 O(n) 时间但仅遍历并置空引用,不触发扩容/缩容逻辑 - 引用稳定:原集合变量仍指向同一对象,不会导致其他持有该引用的地方失效
- 线程安全集合(如
CopyOnWriteArrayList)的clear()也按预期工作,只是开销略高
别用 = new XXX() 替代 clear(),除非你真想换对象
写 list = new ArrayList(); 看似“清空”,实则是创建新对象并让变量指向它。老对象若还有其他引用(比如被另一个类缓存、传入了监听器、放在静态容器里),就根本没被清空,反而造成内存泄漏风险。
常见误用场景:
立即学习“Java免费学习笔记(深入)”;
- 在方法中接收一个
List参数后直接赋值新集合 → 调用方看到的还是旧集合,数据未同步清除 - 把集合存在
ThreadLocal或静态字段中,用= new后旧对象残留,GC 不掉 - 使用 Guava 或 Spring 的不可变集合包装器时,
new出来的对象可能丢失原始配置(如自定义比较器、并发策略)
removeAll() 和 retainAll() 不适合常规清空
removeAll(Collections.emptyList()) 或 retainAll(Collections.emptySet()) 在语义和性能上都不如 clear():
-
removeAll()会遍历当前集合每个元素,再对空集合调用contains()—— 多余开销,且某些实现(如TreeSet)可能触发不必要的比较 -
retainAll()同样要遍历+判断,还可能触发内部结构重排(如LinkedHashSet的链表维护) - 二者都不是原子操作,在并发修改检测(fail-fast)集合中,即使清空过程本身无竞态,也可能因中途被其他线程修改而抛
ConcurrentModificationException
注意 Map 的清空要用 clear(),不是 remove(key)
很多人混淆 Map 和集合的操作:Map 不是 Collection 子接口,但它有 clear() 方法,行为一致——清空所有键值对。
错误做法包括:
- 循环调用
map.remove(key):效率低、易漏、可能 ConcurrentModificationException - 用
map.keySet().clear():看似取巧,但部分实现(如ConcurrentHashMap)的keySet()返回的是视图,clear()会转发到原 map;而有些自定义 Map 实现可能不支持此用法,行为不可靠 - 用
map.entrySet().removeIf(...)清空:绕远路,且 Java 8+ 中虽可用,但比clear()多一层函数调用和 lambda 开销
真正需要区分的是:如果 map 是只读包装(如 Collections.unmodifiableMap()),调用 clear() 会直接抛 UnsupportedOperationException —— 这时候你得确认源头是否可修改,而不是强行绕过。










