size()方法返回集合元素个数,为O(1)时间复杂度,但需防null调用和并发不安全;Map.size()与keySet().size()等价;stream().count()为O(n),不可替代size()。

size() 方法在 Java 集合中的通用行为
size() 是 Collection 接口定义的方法,所有标准集合类(ArrayList、HashSet、LinkedList、HashMap 的 keySet() 等)都实现了它。它的返回值是 int 类型,表示当前集合中元素的个数。
注意:它不递归计算嵌套结构,只统计直接持有的元素数量;对 Map 来说,map.size() 返回的是键值对数量,不是 key 或 value 单独的数量。
-
size()是 O(1) 时间复杂度 —— 内部通常只是读取一个计数字段,不遍历 - 空集合(如新创建的
ArrayList)调用size()返回0,不是null - 如果集合被多个线程并发修改且未加同步,
size()返回值可能不准确(如ArrayList非线程安全)
常见误用:对 null 集合调用 size() 导致 NullPointerException
这是最常踩的坑:直接对可能为 null 的集合变量调用 size(),运行时报 NullPointerException。
Listlist = getFromSomewhere(); // 可能返回 null int count = list.size(); // ❌ 如果 list == null,这里崩
正确做法是显式判空:
立即学习“Java免费学习笔记(深入)”;
- 用
Objects.nonNull(list)+ 三元表达式:int count = Objects.nonNull(list) ? list.size() : 0; - 或提前 guard:
if (list == null) return 0; - 更推荐在方法契约层面避免返回
null—— 改用Collections.emptyList()或Optional
Map 的 size() 和 keySet().size() 是否等价?
等价。对任意 Map 实例 m,m.size() 和 m.keySet().size() 总是相等,因为 Map 的大小定义就是键值对数量,而 keySet() 是其视图,底层共享同一计数逻辑。
但要注意性能和语义差异:
-
m.size()直接返回字段值,开销最小 -
m.keySet().size()多一次方法调用和对象访问,虽仍是 O(1),但无必要 -
m.values().size()同样等价,但values()视图在某些实现(如ConcurrentHashMap)中可能触发轻量初始化,不如直接用size()
Stream.count() 与 Collection.size() 的关键区别
别把 stream().count() 当作 size() 的替代 —— 它们语义和性能完全不同:
-
collection.size():O(1),不触发遍历,不消耗流资源 -
collection.stream().count():O(n),必须完整遍历整个数据源,即使集合本身支持快速获取大小 - 对已排序或过滤过的流(如
list.stream().filter(...).count()),无法绕过计算,此时count()是唯一选择 - 如果只是想知道原始集合大小,用
size();只有在流式处理链中需要“计数”时,才用count()
尤其注意:对并行流调用 count() 不会提升性能,反而增加调度开销 —— 计数操作本身无法真正并行化。
null 检查、流与集合语义混淆、以及对线程安全边界的忽视,才是实际出问题最多的地方。










