如何在 Java 中克隆一个泛型 List?

我有一份 ArrayList<String>,我想退还一份。ArrayList有一个克隆方法,具有以下签名:

public Object clone()

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

273038 次浏览
ArrayList first = new ArrayList ();
ArrayList copy = (ArrayList) first.clone ();
ArrayList newArrayList = (ArrayList) oldArrayList.clone();

我发现使用 addAll 工作得很好。

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

使用括号而不是泛型语法

这也应该有效:

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

我认为使用 CollectionsAPI 应该可以做到这一点:

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

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

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

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

任务完成。

请注意 Object.clone ()有一些主要问题,在大多数情况下不鼓励使用它。请参阅约书亚 · 布洛赫的“ 有效的爪哇”中的第11项以获得完整的答案。我相信您可以在基元类型数组上安全地使用 Object.clone () ,但是除此之外,您需要明智地正确使用和重写 clone。定义一个复制建构子或静态工厂方法来根据语义显式地克隆对象可能更好。

克隆数组列表时要非常小心。爪哇的克隆是肤浅的。这意味着它将只复制数组列表本身,而不复制其成员。因此,如果你有一个数组列表 X1并将其克隆到 X2中,那么 X2中的任何变化也会在 X1中显示出来,反之亦然。当您克隆时,您将只生成一个新的 ArrayList,其中包含指向原始数据库中相同元素的指针。

我不是一个 Java 专业人士,但我有同样的问题,我尝试用这种方法解决。(它假设 t 有一个复制建构子)。

 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);
}
}

这是我用来做这个的代码:

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

希望对你有用

要克隆像 java.util.List这样的通用接口,你只需要强制转换它:

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

这是有点棘手,但它的工作,如果你被限制返回一个 List接口,所以任何人后,你可以实现你的列表,只要他想要的。

我知道这个答案接近于最终的答案,但是我的答案是如何在使用 List(通用的父代)而不是 ArrayList时完成所有这些工作

用 Java8可以用流克隆它。

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

...

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

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

ImmutableList.copyOf(list);
List<String> shallowClonedList = new ArrayList<>(listOfStrings);

请记住,这只是一个浅薄的副本,而不是深刻的。你会得到一个新的列表,但是条目是一样的。对于简单的字符串,这不成问题。当列表条目是对象本身时,获取更加棘手。