如何在Java中克隆通用List?

Bil*_*ard 149 java generics clone arraylist

我有一个ArrayList<String>我想要寄回的副本. ArrayList有一个克隆方法,具有以下签名:

public Object clone()
Run Code Online (Sandbox Code Playgroud)

调用此方法后,如何将返回的Object转换回ArrayList<String>

Tom*_*ine 311

你为什么要克隆?创建新列表通常更有意义.

List<String> strs;
...
List<String> newStrs = new ArrayList<>(strs);
Run Code Online (Sandbox Code Playgroud)

任务完成.

  • 我会关心原始列表使用哪种实现方式吗?我可能关心新列表使用哪种实现. (50认同)
  • 您可能不知道它是什么类型的列表.它可能是LinkedList,MyOwnCustomList或ArrayList的子类,在这种情况下,新建ArrayList将是不正确的类型. (17认同)
  • @Steve Kuo:签名是`ArrayList(Collection <?extends E> c)`意思是什么类型的列表用作参数并不重要. (12认同)
  • @YekhezkelYovel不,它不会. (4认同)
  • 我的意思是它不是一个很深的副本,是吗? (3认同)
  • 根据文档[link](http://docs.oracle.com/javase/1.4.2/docs/api/java/util/ArrayList.html#ArrayList(java.util.Collection))似乎没有复制列表的元素,但使用相同的引用,我是对的吗? (2认同)

Vin*_*vic 58

ArrayList newArrayList = (ArrayList) oldArrayList.clone();
Run Code Online (Sandbox Code Playgroud)

  • 除了遗留代码之外,您应该避免使用原始类型.你最好使用`ArrayList <String> newArrayList =(ArrayList <String>)oldArrayList.clone();`. (46认同)
  • 这对于字符串很好(这就是问题所要求的),但值得注意的是ArrayList.clone将执行浅拷贝,因此如果列表中有可变对象,则不会克隆它们(并且更改一个在一个列表中也将更改另一个列表中的那个. (38认同)
  • 这太糟糕了ArrayList有一个#clone方法,但List本身没有.叹. (20认同)
  • 不相关但在它时:在左侧使用`List <String>`而不是`ArrayList <String>`.这是集合应该在大多数时间使用的方式. (12认同)
  • 我无法使用此方法复制ArrayList.clone()方法无法识别. (2认同)

小智 20

这是我用于此的代码:

ArrayList copy = new ArrayList (original.size());
Collections.copy(copy, original);
Run Code Online (Sandbox Code Playgroud)

希望对你有用

  • 并避免使用原始类型..所以而不是`ArrayList`使用`ArrayList <YourObject>` (3认同)
  • http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#copy-java.util.List-java.util.List- 不起作用,因为列表大小不同. (2认同)

Sim*_*ins 19

使用Java 8,可以使用流克隆它.

import static java.util.stream.Collectors.toList;
Run Code Online (Sandbox Code Playgroud)

...

List<AnObject> clone = myList.stream().collect(toList());
Run Code Online (Sandbox Code Playgroud)

  • 这不是深拷贝,一个列表元素的变化可以在另一个列表中看到 (2认同)
  • 在问题的哪个地方指定需要深拷贝?假设需要另一个包含相同对象的集合。如果您想沿着深层复制路线走下去,那么您将打开一堆全新的蠕虫。 (2认同)

Jul*_*ang 16

请注意,Object.clone()存在一些主要问题,在大多数情况下不鼓励使用它.请参阅Joshua Bloch的" Effective Java "中的第11项,以获得完整的答案.我相信你可以安全地在原始类型数组上使用Object.clone(),但除此之外,你需要明智地正确使用和重写克隆.您可能最好定义一个复制构造函数或静态工厂方法,根据您的语义显式克隆对象.


Aar*_*ron 14

我认为这应该使用Collections API来解决问题:

注意:复制方法以线性时间运行.

//assume oldList exists and has data in it.
List<String> newList = new ArrayList<String>();
Collections.copy(newList, oldList);
Run Code Online (Sandbox Code Playgroud)

  • 为什么不使用新的ArrayList <String>(oldList)? (13认同)
  • 我认为这不起作用,来自doc*目的地列表必须至少与源列表一样长.如果它更长,则目标列表中的其余元素不受影响. (3认同)

All*_*nde 8

我发现使用addAll工作正常.

ArrayList<String> copy = new ArrayList<String>();
copy.addAll(original);
Run Code Online (Sandbox Code Playgroud)

使用括号而不是泛型语法

  • 这对字符串有用,但不适用于可变对象.你也想要克隆它们. (4认同)
  • 为什么不使用`new ArrayList <String>(original)`? (4认同)

Uri*_*lit 6

如果你想要这个以便能够在getter中返回List,那么最好这样做:

ImmutableList.copyOf(list);
Run Code Online (Sandbox Code Playgroud)


Rob*_*ert 6

List<String> shallowClonedList = new ArrayList<>(listOfStrings);
Run Code Online (Sandbox Code Playgroud)

请记住,这只是一个浅拷贝而不是深拷贝,即。您会得到一个新列表,但条目是相同的。这对于简单的字符串没有问题。当列表条目本身是对象时,Get 会更加棘手。