提问人:Gamaray 提问时间:9/1/2022 最后编辑:Alexander IvanchenkoGamaray 更新时间:9/1/2022 访问量:323
如何防止一个 ArrayList 更改另一个 ArrayList
How can I prevent one ArrayList changing another
问:
我有两个相同的 s,比如 和 。ArrayList
l1
l2
例如,两者都是多维的。ArrayList<ArrayList<Integer>>
当我创建和填充时,我用来初始化 .如果这些是单个维度的,我的编辑将保持不变,但由于它们不是,因此添加新的 也会更改。但是,如果我要向它添加一个新的,则不会做任何事情。l1
new ArrayList<>(l1);
l2
ArrayList
l2
l1
Integer
l2
l1
ArrayList
l1
可以做些什么来确保更改元素不会篡改?l2
l1
例:
ArrayList<ArrayList<Integer>> l1 = new ArrayList<>();
for (var x = 0; x < 10; x++) {
l1.add(new ArrayList<>());
for (var y = 0; y < 10; y++) {
l1.get(x).add(y);
}
}
ArrayList<ArrayList<Integer>> l2 = new ArrayList<ArrayList<Integer>>(l1);
//Should not change l1
l2.get(0).add(999);
答:
1赞
Gatusko
9/1/2022
#1
创建这两个数组时。我们只创建了 ArrayList 的两个新对象,但没有在列表中创建对象的新实例。因此,如果 L1 进行更改,则这两个 ArrayLists 内部的任何内容都将反映更改,因为这两个 ArrayList 引用了内存中的同一对象。
为了使这项工作,不要像这样初始化
ArrayList<ArrayList<Integer>> l2 = new ArrayList<ArrayList<Integer>>(l1);
遍历 l1 并创建新对象。
评论
0赞
Gamaray
9/1/2022
谢谢,这确实有效,唯一的问题是该方法效率有点低(这将在神经网络的每个时代发生),但如果必须完成,则必须完成。再次感谢。
1赞
Alexander Ivanchenko
9/1/2022
#2
集合框架中的复制构造函数始终执行浅拷贝,而不是深拷贝,正如你所期望的那样。
ArrayList(Collection<? 扩展 E> c)
的 Javadoc 说:
构造一个列表,其中包含指定集合的元素,按集合的迭代器返回这些元素的顺序排列。
也就是说,生成的列表将包含完全相同的元素,而不是它们的副本。也就是说,在你的情况下,引用相同的内部列表。
因此,您需要手动复制嵌套列表中的每个元素:
public static <T> List<List<T>> copyNestedList(List<List<T>> list) {
List<List<T>> copy = new ArrayList<>();
for (List<T> l: list) {
copy.add(new ArrayList<>(l));
}
return copy;
}
如果您对 Stream API 感到满意,您可以这样做:
public static <T> List<List<T>> copyNestedList(List<List<T>> list) {
return list.stream()
.map(ArrayList::new)
.collect(Collectors.toList());
}
评论
0赞
Gamaray
9/1/2022
谢谢,是的,这就是我最终所做的。非示例数组是一个神经网络,因此它具有相当多的维度,但值得庆幸的是,循环似乎并没有过多地减慢优化速度。
0赞
Alexander Ivanchenko
9/1/2022
@Gamaray 没有干净而简单的方法来制作具有任意深度的嵌套的深层副本。就性能而言,普通循环是您可以使用的最佳工具。List
1赞
F. DePa
9/1/2022
#3
您可以手动创建一个新列表,而无需引用原始列表
ArrayList<ArrayList<Integer>> l1 = new ArrayList<>();
for (var x = 0; x < 2; x++) {
l1.add(new ArrayList<>());
for (var y = 0; y < 2; y++) {
l1.get(x).add(y);
}
}
ArrayList<ArrayList<Integer>> l2 = new ArrayList<ArrayList<Integer>>();
for (int i = 0;i < l1.size(); i++){
ArrayList<Integer> tmp = new ArrayList<Integer>();
for (int j = 0;j < l1.get(i).size(); j++){
tmp.add(l1.get(i).get(j));
}
l2.add(tmp);
}
评论