Java-从旧列表创建新列表,旧列表也会被修改

Java-从旧列表创建新列表,旧列表也会被修改,java,arraylist,collections,Java,Arraylist,Collections,我使用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"));

我使用
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());
        }

如何防止这种行为并保持旧列表不变?

Java在列表中存储对对象的引用。因此,如果创建一个复制列表,但列表对象不同,它仍然使用对a对象的相同引用,换句话说,两个列表中的a对象相同。若要防止这种情况发生,需要对对象进行克隆拷贝。结果如下所示:

List<A> newList = list.stream.map(a -> new A(a.getContent()).collect(Collectors.toList());
List newList=List.stream.map(a->newa(a.getContent()).collect(Collectors.toList());
或者,如果您在

List<A> newList = list.stream.map(A::clone).collect(Collectors.toList());
List newList=List.stream.map(A::clone.collect(Collectors.toList());

Java将对对象的引用存储在列表中。所以,如果只创建一个副本列表,则列表对象是不同的,它仍然使用对a对象的相同引用,换句话说,两个列表中都有相同的a对象。若要防止这种情况发生,则需要创建a对象的克隆副本。结果如下所示:

List<A> newList = list.stream.map(a -> new A(a.getContent()).collect(Collectors.toList());
List newList=List.stream.map(a->newa(a.getContent()).collect(Collectors.toList());
或者,如果您在

List<A> newList = list.stream.map(A::clone).collect(Collectors.toList());
List newList=List.stream.map(A::clone.collect(Collectors.toList());
(您的代码的第一个版本有一个打字错误。我假设您的真实代码中不存在这个错误。)

真正的问题是,您将对相同对象的引用放入两个单独的列表中。当您调用
set
方法时,这是在修改对象…而不是列表。当然,您可以通过任一列表看到对对象的修改

如果不希望发生这种情况,则必须将第一个列表中对象的副本添加到第二个列表中。为此,您需要实现一种方法来复制
a
的实例。您可以使用:

  • 复制构造函数
  • 复制或
    克隆
    方法
  • 序列化和反序列化,或
  • 特别代码
一旦你有了复制
a
的方法,你只需迭代第一个列表,将其条目的副本添加到第二个列表中。

(你的代码的第一个版本有一个拼写错误。我假设你的真实代码中不存在这个错误。)

真正的问题是,您将对相同对象的引用放入两个单独的列表中。当您调用
set
方法时,这是在修改对象…而不是列表。当然,您可以通过任一列表看到对对象的修改

如果不希望发生这种情况,则必须将第一个列表中对象的副本添加到第二个列表中。为此,您需要实现一种方法来复制
a
的实例。您可以使用:

  • 复制构造函数
  • 复制或
    克隆
    方法
  • 序列化和反序列化,或
  • 特别代码

一旦你有了复制
a
的方法,你只需迭代第一个列表,将其条目的副本添加到第二个列表中。

你只需要做一个浅层副本,你还必须克隆/复制
a
对象,并将副本放在新列表中而不是原始列表中。你总是在使用新列表。输出正确,你只需要复制原始列表中对象的引用。是的,在您的第一个循环中看起来像是打印错误。您正在修改的不是新列表,而是新列表中的对象。这是一个很大的区别。我已经更正了输入错误。您只做了一个浅层副本,您必须克隆/复制
a
对象,并将副本放在新列表中,而不是您的原始列表中We’我们总是使用新列表。输出是正确的。您只复制了原始列表中对象的引用。是的,在第一个循环中看起来像是打印错误。您修改的不是新列表,而是新列表中的对象。这是一个很大的区别。我已更正了错误。