【问题标题】:Java-How can i use correctly list.copyOf? [duplicate]Java-我怎样才能正确使用list.copyOf? [复制]
【发布时间】:2019-07-17 23:31:28
【问题描述】:

我的问题是我需要复制一个列表,但需要一个深拷贝。当我修改列表a 时,我不想修改列表b。我使用JDK11,所以我可以使用list.copyOf,但是当我修改a时,b也被修改了。我做错了吗?

b = List.copyOf(a);
System.out.println("A start:" + b.get(2).getSeating());
System.out.println("B start:" + b.get(2).getSeating());
a.get(2).setSeating(27);
System.out.println("Hi there" );
System.out.println("A end:" + a.get(2).getSeating());
System.out.println("B end:" + b.get(2).getSeating());

该分配的输出

【问题讨论】:

  • “我做错了什么吗?” 是的,你错误地认为List.copyOf() 是一个深拷贝。 javadoc 没有提到深拷贝,那你为什么相信呢?
  • 返回一个不可修改的列表,其中包含给定集合的元素,按其迭代顺序。给定的 Collection 不得为 null,并且不得包含任何 null 元素。如果随后修改了给定的 Collection,则返回的 List 将不会反映此类修改。
  • 是的,javadoc 就是这么说的。它没有说它正在做一个深拷贝。它正在将 references 复制到列表中的元素,而不是元素本身。复制的 list 是不可修改的。元素不是,它们在旧列表和新列表之间共享。这就是浅拷贝的意思。所以我再问一次,为什么你认为copyOf 是在进行deep 复制?或者我应该问你是否知道什么是深拷贝?
  • 我知道深拷贝是什么意思,但我认为 java 应该提供一种更简单的方法来做到这一点,因为有时拥有原件来修改元素和原件很重要,以防你想要原始值。
  • Java 确实有一个简单的方法来做到这一点,clone() 方法,但只有 可以确定如何正确复制对象,即哪些字段需要深- 已复制,所以需要告诉Java如何做的细节。

标签: java list deep-copy


【解决方案1】:

copyOf 方法不会进行深拷贝,根据documentation 它返回一个非可变视图,即只读列表。它不会复制列表中的元素。要进行深度复制,您基本上需要遍历集合并将元素一个一个地深度复制到新集合中。在一般情况下,这可能很棘手。有些对象支持克隆,有些对象有自定义复制方法,但在一般情况下,Java 没有始终有效的深层复制方法。

简而言之,解决方案会因列表中的内容而异。由于它似乎是您的应用程序中的自定义对象,因此最简单的方法可能是遍历列表并将实例复制到一个新列表中,并使用您在类中提供的复制构造函数或克隆方法。

【讨论】:

  • 当你说克隆方法时,你会怎么做?,因为我发现同样的问题是我在新列表中保留了对列表对象的引用
  • @AlexFerre 阅读重复链接。它的存在是有原因的。
  • @Andreas 我认为另一个答案不是很好,因为它没有给出如何覆盖克隆方法的示例。我再说一遍,我认为必须重写一个方法来获得一个简单的数组副本应该由 java 来规范。对于像我这样的菜鸟来说,这既棘手又复杂
  • 深拷贝很棘手,没有好的标准解决方案。请参阅baeldung.com/java-deep-copy 了解包括克隆在内的一些替代方案。如果您控制源代码,我个人建议使用复制构造函数(即采用另一个类似对象并复制所有字段的构造函数)。这样,您可以根据要求深入复制一些字段,并使用直接参考副本来复制一些字段。
  • @AlexFerre “另一个答案 [...] 没有给出如何覆盖克隆方法的示例”。当然可以。看看second answer。这不是一个很好的例子,但它肯定是一个例子。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-14
  • 2016-06-15
  • 2021-09-24
  • 1970-01-01
  • 1970-01-01
  • 2018-07-09
  • 2016-11-24
相关资源
最近更新 更多