我已经使用addAll()
方法从旧列表创建了新列表,当我尝试修改新列表时,旧列表也被修改了。
例如-
List<A> list = new ArrayList<A>();
list.add(new A("something1"));
list.add(new A("something2"));
list.add(new A("something3"));
list.add(new A("something4"));
List<A> newList = new ArrayList<A>();
newList.addAll(list);
for(A a1 : newList){
a1.setA("something new");
}
System.out.println("list----------------");
for(A a1 : list){
System.out.println(a1.toString());
}
System.out.println("new list----------------");
for(A a1 : newList){
System.out.println(a1.toString());
}
输出-
list----------------
A [a=something new]
A [a=something new]
A [a=something new]
A [a=something new]
new list----------------
A [a=something new]
A [a=something new]
A [a=something new]
A [a=something new]
如何防止这种行为并使旧列表保持原样?
答案 0 :(得分:2)
Java将对对象的引用存储在列表中。因此,如果仅创建一个复制列表,则列表对象是不同的,它仍然使用对A对象的相同引用,换言之,两个列表中都使用相同的A对象。如果要防止这种情况,则需要制作A对象的克隆副本。结果将如下所示:
List<A> newList = list.stream.map(a -> new A(a.getContent()).collect(Collectors.toList());
或者如果您在A中有一个克隆/复制方法
List<A> newList = list.stream.map(A::clone).collect(Collectors.toList());
答案 1 :(得分:2)
(您的代码的第一个版本有一个错字。我假设您的真实代码中不存在错字。)
真正的问题是,您要将对相同对象的引用放入两个单独的列表中。当您调用set
方法时,这是在修改对象,而不是列表。自然,您可以通过任一列表查看对对象的修改。
如果您不希望发生这种情况,则必须将第一个列表中的对象的副本添加到第二个列表中。为此,您需要实现一种复制A
实例的方法。您可以使用:
clone
方法一旦您有一种复制A
的方法,您只需遍历第一个列表,将其条目的副本添加到第二个列表中即可。