【问题标题】:Copy constructor of Array List数组列表的复制构造函数
【发布时间】:2018-07-14 09:01:27
【问题描述】:

我刚刚读到人们认为的 ArrayList 的深拷贝

new ArrayList<>(originalList);

将创建一个浅拷贝。而且我写了一个小demo

    ArrayList<String> originalNameList = new ArrayList<>(Arrays.asList("Anna", "Betty", "Chris"));
    List<String> copyNameList1=originalNameList;
    List<String> copyNameList2= new ArrayList<>(originalNameList);

    originalNameList.add("Duke");
    copyNameList1.add("Ellen");
    copyNameList1.set(1,"Bill");
    copyNameList2.set(0,"Andy");

    System.out.println("originalNameList = " + originalNameList);
    System.out.println("copyNameList1    = " + copyNameList1);
    System.out.println("copyNameList2    = " + copyNameList2);

结果:

originNameList = [Anna, Bill, Chris, Duke, Ellen]
copyNameList1  = [Anna, Bill, Chris, Duke, Ellen]
copyNameList2  = [Andy, Betty, Chris]

我觉得 ArrayList 的拷贝构造函数没那么浅。那为什么人们会这样说?是否有某些级别的深拷贝? 非常感谢!

【问题讨论】:

  • 结果与执行浅拷贝完全一样。您的预期输出是什么,为什么?
  • 你对浅层和深层的定义似乎不同。浅拷贝意味着只复制对列表内对象的引用。这就是发生的事情。深拷贝意味着列表中的对象本身被复制(即,如果您愿意,可以克隆),并且副本将存储到新列表中。
  • 在 Java 中 String 类的实例应该是不可变的。您如何观察不可变对象集合的浅拷贝和深拷贝之间的区别?
  • @PeterT 与==...
  • @PeterT 知道了,demo 应该是可变对象,tks

标签: java arraylist copy-constructor deep-copy


【解决方案1】:

您对“浅”和“深”副本的定义似乎是错误的。您似乎认为浅拷贝意味着“复制对对象的引用”,如下所示:

List<String> copyNameList1=originalNameList;

而“深”副本会创建一个新的数组列表:

List<String> copyNameList2= new ArrayList<>(originalNameList);

请注意,以上是一个误解。

浅拷贝实际上意味着创建一个具有相同元素的新数组列表,而深拷贝意味着创建一个包含原始数组列表中元素副本的新数组列表。

这里最大的区别是“数组列表中的元素是否被复制”。

假设您有一个数组列表对象a1。它包含对 3 个三个对象 obj1obj2obj3 的引用。

a1 的浅拷贝将创建一个新的数组列表对象 a2,其中包含对相同 obj1obj2obj3 对象的引用。

a1 的深层副本将创建一个新的数组列表对象a2,其中包含对obj4obj5obj6 的引用,其中obj4obj5obj6 是副本obj1obj2obj3

这里有两种方法可以显示浅拷贝和深拷贝中发生的情况:

static ArrayList<String> shallowCopy(ArrayList<String> original) {
    ArrayList<String> copy = new ArrayList<>();
    for (String s : original) {
        copy.add(s);
    }
    return copy;
}

static ArrayList<String> deepCopy(ArrayList<String> original) {
    ArrayList<String> copy = new ArrayList<>();
    for (String s : original) {
        String copyOfString = new String(s); // note that each string is copied as well
        copy.add(copyOfString);
    }
    return copy;
}

一般来说,深拷贝也会复制目标对象所引用的对象。

【讨论】:

  • 我的错误是创建了一个字符串类型的样本,它是不可变类型。我只是用对象类型创建其他对象,并按照您所说的那样清楚地看到它。非常感谢!
猜你喜欢
  • 2019-05-03
  • 1970-01-01
  • 1970-01-01
  • 2013-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多