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

时间:2018-10-17 13:16:32

标签: 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"));
        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]

如何防止这种行为并使旧列表保持原样?

2 个答案:

答案 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的方法,您只需遍历第一个列表,将其条目的副本添加到第二个列表中即可。