Java中ArrayList.addAll性能对比:空集合是否需前置判空?
性能对比:先判断isEmpty还是直接调用ArrayList.addAll
针对你提到的场景——待添加的list2有三分之二的概率为空,我们结合Java ArrayList的底层实现和概率加权开销来分析两种方案的性能差异:
1. 先明确核心方法的内部逻辑
先看ArrayList中关键方法的源码实现:
// isEmpty() 直接读取成员变量判断,O(1)开销 public boolean isEmpty() { return size == 0; } // addAll(int index, Collection<? extends E> c) 处理空集合的逻辑 public boolean addAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index); // 校验index合法性,传入0时几乎无开销 Object[] a = c.toArray(); // 空ArrayList会返回长度为0的数组 int numNew = a.length; if (numNew == 0) return false; // 空集合直接返回,不执行后续操作 // 非空时的扩容、数组复制等 heavy 操作 }
2. 两种方案的开销对比
空集合场景(占2/3概率)
- 方案1(先判断再调用):仅执行一次
isEmpty()判断(读取size变量+布尔判断),直接跳过addAll操作,开销极小。 - 方案2(直接调用addAll):需要进入
addAll方法,执行index校验、toArray()调用(空集合返回空数组)、数组长度判断后返回。即便JVM做了内联优化,这些步骤的累计开销还是会比单纯的isEmpty()判断高——冷启动阶段(未触发JIT编译)差异更明显。
非空集合场景(占1/3概率)
- 方案1:多一次
isEmpty()判断(O(1),微乎其微的开销),后续addAll的执行逻辑和方案2完全一致。 - 方案2:直接进入
addAll执行添加逻辑,少一次isEmpty()判断,但这点差异可以忽略不计。
3. 最终结论
从性能角度看,先执行if (!list2.isEmpty())判断再调用addAll的方案更优——因为空集合场景占比高达2/3,累计下来能省下大量无意义的方法调用和内部校验步骤。
如果优先考虑代码简洁性,直接调用addAll也完全可行(方法本身支持空集合,不会抛出异常),但在你的特定概率场景下,性能收益是明确存在的。
内容的提问来源于stack exchange,提问作者CrystalSpider
相关产品推荐
相关产品推荐

