Collections.addAll() 初始化大型列表更快,因其减少方法调用、避免重复扩容、绕过Iterator抽象层,并一次性预估容量;而循环add()或addAll(Arrays.asList())多层间接、频繁扩容、易出错。

直接用 Collections.addAll() 初始化大型列表,比循环调用 add() 快,核心在于减少方法调用开销、避免重复扩容判断和绕过迭代器抽象层。
跳过 Iterator 抽象,直操作数组底层
addAll() 方法接收可变参数,经 varargs 机制直接生成一个 Object[] 数组;内部遍历该数组时,是普通 for 循环索引访问,时间复杂度 O(n),无对象创建、无 hasNext()/next() 调用。而循环写 add() 或用 addAll(Arrays.asList(...)),后者必须先构造 ArrayList(由 Arrays.asList 返回的 List 是数组代理,但 addAll 内部仍要走 Iterator),多一层间接访问,还触发额外的对象分配。
批量扩容一次到位,避免反复 resize
ArrayList 的 add() 每次检查容量,不够就扩容(原数组复制)。对百万级初始化,逐个 add 可能触发十几次扩容,每次复制前序所有元素。Collections.addAll() 在开始前可预估元素数量(varargs 数组长度已知),多数实现会一次性确保足够容量——哪怕没显式指定初始容量,JVM 和集合类优化也倾向更早完成扩容决策。
代码简洁且语义明确,减少出错可能
用 Collections.addAll(list, e1, e2, ..., eN) 一行完成初始化,逻辑集中、无可省略步骤;而手动循环 add 容易漏写边界、误用索引、在并发或不可变包装场景下忽略返回值或异常。尤其当 list 是 Collections.unmodifiableList() 包装过的,add() 会直接抛 UnsupportedOperationException,但错误发生在运行时第 N 次调用,不如一次性调用失败来得早、来得明确。
适用场景与注意事项
适用于初始化阶段批量塞入几十到上百万个字面量或已知数组元素;不适用于动态条件判断后选择性添加——那仍需 if + add。注意:它不能替代 addAll(Collection),后者专用于合并另一个集合;若手头是 Collection 实例,直接用 list.addAll(other) 更自然,性能也不差。

















