如何在Java中克隆通用列表?

如何在Java中克隆通用列表?

How do I clone a generic List in Java?

我有一个ArrayList,我想返回它的副本。 ArrayList具有一个具有以下签名的克隆方法:

1
public Object clone()

调用此方法后,如何将返回的对象强制转换回ArrayList


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

1
2
3
List<String> strs;
...
List<String> newStrs = new ArrayList<>(strs);

任务完成。


1
ArrayList newArrayList = (ArrayList) oldArrayList.clone();


这是我使用的代码:

1
2
ArrayList copy = new ArrayList (original.size());
Collections.copy(copy, original);

希望对您有用


使用Java 8可以将其克隆为流。

1
import static java.util.stream.Collectors.toList;

...

1
List<AnObject> clone = myList.stream().collect(toList());

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


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

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

1
2
3
//assume oldList exists and has data in it.
List<String> newList = new ArrayList<String>();
Collections.copy(newList, oldList);

我发现使用addAll可以正常工作。

1
2
ArrayList<String> copy = new ArrayList<String>();
copy.addAll(original);

使用括号而不是泛型语法


如果您希望这样做,以便能够在getter中返回List,则最好这样做:

1
ImmutableList.copyOf(list);

要克隆java.util.List之类的通用接口,您只需要强制转换即可。这是一个例子:

1
2
List list = new ArrayList();
List list2 = ((List) ( (ArrayList) list).clone());

这有点棘手,但是,如果您被限制返回List接口,那么它就可以工作,因此您之后的任何人都可以在需要时实现列表。

我知道这个答案接近最终答案,但是我的答案回答了在使用List-泛型父级-而不是ArrayList时如何完成所有这些操作


1
List<String> shallowClonedList = new ArrayList<>(listOfStrings);

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


克隆ArrayList时要非常小心。用Java克隆很浅。这意味着它将仅克隆Arraylist本身,而不克隆其成员。因此,如果您具有ArrayList X1并将其克隆到X2中,则X2中的任何更改也将在X1中显示,反之亦然。克隆时,您将只生成一个新的ArrayList,该ArrayList带有指向原始元素中相同元素的指针。


这也应该起作用:

1
2
ArrayList<String> orig = new ArrayList<String>();
ArrayList<String> copy = (ArrayList<String>) orig.clone()

我不是Java专业人员,但是我有同样的问题,因此尝试通过这种方法解决。 (假设T有一个副本构造函数)。

1
2
3
4
5
6
7
8
9
10
11
12
 public static <T extends Object> List< T > clone(List< T > list) {
      try {
           List< T > c = list.getClass().newInstance();
           for(T t: list) {
             T copy = (T) t.getClass().getDeclaredConstructor(t.getclass()).newInstance(t);
             c.add(copy);
           }
           return c;
      } catch(Exception e) {
           throw new RuntimeException("List cloning unsupported",e);
      }
}

1
2
ArrayList first = new ArrayList ();
ArrayList copy = (ArrayList) first.clone ();


推荐阅读