Collections.nCopies(n, element)返回不可变列表,需用ArrayList构造函数转为可变列表才能支持set操作;直接调用会抛UnsupportedOperationException。

可以通过 Collections.nCopies(n, element) 生成一个不可变的、包含 n 个相同元素的列表,再将其作为参数传入 ArrayList(或其他可变列表)的构造函数,从而得到一个**可修改的、固定长度的占位符列表**。
为什么需要配合列表构造函数?
Collections.nCopies() 返回的是一个轻量级的不可变列表(内部基于数组实现,不真正复制元素),它不支持 set()、add()、remove() 等修改操作。直接使用会抛出 UnsupportedOperationException。所以必须用它来初始化一个真正的可变列表。
标准写法(推荐)
以初始化长度为 5、每个元素为 null 的 ArrayList 为例:
List<String> list = new ArrayList<>(Collections.nCopies(5, null));
这样得到的 list 是:
- 长度固定为 5(初始容量和大小都是 5)
- 所有元素均为
null(或你指定的任意默认值,如""、0、Optional.empty()等) - 支持后续任意位置的
set(i, value)赋值 - 不支持
add()或remove()(否则会改变长度,违背“固定长度”初衷;若需扩容/缩容,应另作设计)
常见用途与注意事项
- 批量占位 + 后续填充:适合读取固定字段数的记录(如 CSV 行、数据库结果集列),先占位再按索引赋值
-
避免空指针 & 长度越界:初始化后
list.size() == n,可安全调用get(i)(只要i ) -
注意引用共享问题:若
element是可变对象(如new ArrayList()),所有位置将引用同一个实例 —— 修改任一位置的元素内容,会影响全部。此时应改用循环初始化或Stream.generate() -
性能友好:
nCopies不真正创建n个对象,只是逻辑重复;构造ArrayList时才分配底层数组并复制引用(对null或不可变对象很高效)
替代方案对比(简要)
不用 nCopies 也能实现,但不够简洁:
- 循环
add(null):代码长,且可能触发多次扩容(除非预设初始容量) -
Arrays.asList(new String[5]):生成不可变列表,仍需套一层ArrayList构造 -
Stream.generate(() -> null).limit(5).collect(Collectors.toCollection(ArrayList::new)):功能等价,但开销略大,可读性弱
因此 new ArrayList(Collections.nCopies(n, value)) 是兼顾简洁性、可读性与效率的标准做法。

















