用 isEmpty() 判断集合是否为空最安全,但需先判 null;CollectionUtils.isEmpty() 是生产首选,它内部同时检查 null 和空集合。

用 isEmpty() 判断集合是否为空最安全
Java 集合类(ArrayList、HashSet、LinkedList 等)都继承自 Collection 接口,该接口定义了 isEmpty() 方法——它明确语义为“当前集合不含任何元素”,返回 boolean,且时间复杂度为 O(1)。
常见错误是用 size() == 0 替代,虽然多数实现里等价,但存在隐患:
-
size()在某些懒加载或代理集合中可能触发计算或副作用(如 Hibernate 的延迟初始化集合调用size()会强制加载) -
isEmpty()是契约方法,语义清晰;size() == 0是推导逻辑,可读性略差 - 部分不可变集合(如
ImmutableList)虽无此问题,但统一用isEmpty()更具一致性
必须先判空再调用 isEmpty(),否则 NPE
isEmpty() 方法本身不能处理 null 引用。如果集合变量为 null,直接调用会抛出 NullPointerException。
典型错误写法:
if (list.isEmpty()) { ... }(当 list 为 null 时崩溃)
立即学习“Java免费学习笔记(深入)”;
正确做法始终前置 null 检查:
- 手动判断:
list != null && list.isEmpty() - 使用
Objects.nonNull(list) && list.isEmpty() - 使用 Guava:
!Lists.newArrayList().isEmpty()不适用,应改用Iterables.isEmpty(list)(它内部已处理null) - 使用 Apache Commons Collections:
CollectionUtils.isEmpty(collection)—— 这是唯一一个同时检查null和空的工具方法
CollectionUtils.isEmpty() 是生产环境首选
在 Spring 或 Apache Commons 项目中,CollectionUtils.isEmpty() 应作为默认选择。它内部逻辑简洁可靠:
public static boolean isEmpty(Collection coll) {
return coll == null || coll.isEmpty();
}
优势明显:
- 一行代码覆盖
null+ 空集合两种边界情况 - 避免手写
!= null时漏掉括号导致逻辑错误(如list != null && list.isEmpty()写成list != null && list.isEmpty()看似没问题,但多人协作中易被误改) - 与
StringUtils.isEmpty()、ArrayUtils.isEmpty()命名和行为一致,降低认知成本 - 不引入运行时开销,纯逻辑判断
Stream 判断空集合要小心 count() 性能陷阱
有人试图用 Stream API 判断空集合:
long count = list.stream().count();然后比较
count == 0。这完全错误:
-
count()是终端操作,必须遍历全部元素,时间复杂度 O(n),而isEmpty()是 O(1) - 对
LinkedList等不支持随机访问的集合,size()本身已是 O(n),再套一层stream().count()是双重浪费 - 若集合含大量数据或 IO 相关(如数据库游标封装的集合),
count()可能引发意外加载或超时 - 真正需要 Stream 场景(如过滤后判空),应改用
findAny().isPresent():boolean hasElement = list.stream().anyMatch(x -> true); // 等价于 !isEmpty()
但注意:这仍不如原生isEmpty()直观高效,仅在已处 Stream 流程中才考虑
集合状态检查这件事,表面简单,实际踩坑点集中在 null 处理和 API 语义混淆上。别为了“看起来函数式”而绕远路,原生 isEmpty() 加 CollectionUtils 就够用了。










