简体   繁体   English

如何在Java中克隆通用List?

[英]How do I clone a generic List in Java?

I have an ArrayList<String> that I'd like to return a copy of. 我有一个ArrayList<String> ,我想返回一份副本。 ArrayList has a clone method which has the following signature: ArrayList有一个克隆方法,它具有以下签名:

public Object clone()

After I call this method, how do I cast the returned Object back to ArrayList<String> ? 在我调用此方法之后,如何将返回的Object转换回ArrayList<String>

Why would you want to clone? 你为什么要克隆? Creating a new list usually makes more sense. 创建新列表通常更有意义。

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

Job done. 任务完成。

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

This is the code I use for that: 这是我用于此的代码:

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

Hope is usefull for you 希望对你有用

With Java 8 it can be cloned with a stream. 使用Java 8,可以使用流克隆它。

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

... ...

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

Be advised that Object.clone() has some major problems, and its use is discouraged in most cases. 请注意,Object.clone()存在一些主要问题,在大多数情况下不鼓励使用它。 Please see Item 11, from " Effective Java " by Joshua Bloch for a complete answer. 请参阅Joshua Bloch的“ Effective Java ”中的第11项,以获得完整的答案。 I believe you can safely use Object.clone() on primitive type arrays, but apart from that you need to be judicious about properly using and overriding clone. 我相信你可以安全地在原始类型数组上使用Object.clone(),但除此之外,你需要明智地正确使用和重写克隆。 You are probably better off defining a copy constructor or a static factory method that explicitly clones the object according to your semantics. 您可能最好定义一个复制构造函数或静态工厂方法,根据您的语义显式克隆对象。

I think this should do the trick using the Collections API: 我认为这应该使用Collections API来解决这个问题:

Note : the copy method runs in linear time. 注意 :复制方法以线性时间运行。

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

I find using addAll works fine. 我发现使用addAll工作正常。

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

parentheses are used rather than the generics syntax 使用括号而不是泛型语法

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

ImmutableList.copyOf(list);

To clone a generic interface like java.util.List you will just need to cast it. 要克隆像java.util.List这样的通用接口,您只需要转换它。 here you are an example: 在这里你是一个例子:

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

It is a bit tricky, but it works, if you are limited to return a List interface, so anyone after you can implement your list whenever he wants. 这有点棘手,但如果你只能返回一个List界面,它就可以了,所以你之后的任何人都可以随时实现你的列表。

I know this answer is close to the final answer, but my answer answers how to do all of that while you are working with List -the generic parent- not ArrayList 我知道这个答案接近最终答案,但我的答案回答了如何在使用List时完成所有这些 - 通用父级 - 而不是ArrayList

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

Keep in mind that this is only a shallow not a deep copy, ie. 请记住,这只是一个浅而非深的副本,即。 you get a new list, but the entries are the same. 你得到一个新的列表,但条目是相同的。 This is no problem for simply strings. 简单的字符串就没问题了。 Get's more tricky when the list entries are objects themself. 当列表条目是对象本身时,变得更棘手。

This should also work: 这应该也有效:

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

Be very careful when cloning ArrayLists. 克隆ArrayLists时要非常小心。 Cloning in java is shallow. 在Java中克隆很浅。 This means that it will only clone the Arraylist itself and not its members. 这意味着它只会克隆Arraylist本身而不是其成员。 So if you have an ArrayList X1 and clone it into X2 any change in X2 will also manifest in X1 and vice-versa. 因此,如果您有一个ArrayList X1并将其克隆到X2中,X2中的任何更改也将在X1中显示,反之亦然。 When you clone you will only generate a new ArrayList with pointers to the same elements in the original. 克隆时,您将只生成一个新的ArrayList,其中包含指向原始元素中相同元素的指针。

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

I am not a java professional, but I have the same problem and I tried to solve by this method. 我不是一个java专业人士,但我有同样的问题,我试图通过这种方法解决。 (It suppose that T has a copy constructor). (假设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);
      }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM