Collections.nCopies() 返回只读视图,底层共享引用,适用于不可变类型或只读场景;若需独立可变对象,应使用 Stream.generate() 或循环构造。

用 Collections.nCopies() 创建不可变重复列表时,别直接当普通 List 用
它返回的是只读视图,底层共享同一引用 —— 所以如果你传入的是可变对象(比如 new ArrayList()),所有位置都指向同一个实例。修改其中任意一个,整个列表“全跟着变”。
- 正确场景:初始化
String、Integer等不可变类型,或仅作只读用途 - 错误写法:
List<arraylist>> list = Collections.nCopies(3, new ArrayList())</arraylist>→ 三个元素其实是同一个ArrayList实例 - 想每个都是独立对象?得配合
Stream.generate()或循环构造,不能只靠nCopies
Collections.nCopies() 的参数边界和性能表现
第一个参数是数量,必须 ≥ 0;负数会抛 IllegalArgumentException;第二个参数是填入的元素,可以为 null(生成的列表里对应位置就是 null)。
- 时间复杂度 O(1),不真正创建
n个对象,只是逻辑上“看起来有 n 份” - 内存占用极小,适合做大容量只读占位,比如初始化 10 万长度的默认值列表
- 但调用
get(i)是 O(1),而set(i, x)会直接抛UnsupportedOperationException
替代方案:需要可变且独立副本时怎么写
如果目标是“n 个互不影响的可变对象”,nCopies 不适用,必须显式构造。
- Java 8+ 推荐:
List<myobj> list = Stream.generate(MyObj::new).limit(n).collect(Collectors.toList())</myobj> - 传统写法:
List<myobj> list = new ArrayList(n); for (int i = 0; i </myobj> - 注意:不要写成
Collections.nCopies(n, new MyObj())—— 这仍是单实例复用,不是复制
常见报错:为什么 add() 或 remove() 会失败
因为 Collections.nCopies() 返回的是 java.util.Collections$CopiesList,内部没有实现结构性修改方法。
- 触发异常:
UnsupportedOperationException,错误信息类似"add" not supported - 哪怕你把它赋给
List接口变量,也不改变其不可变本质 - 如果后续要增删,必须转成可变实现:
new ArrayList(Collections.nCopies(n, "x"))—— 但注意这会真实复制引用(不是深拷贝)
nCopies、Stream.generate,还是老老实实写循环。

















