如何复制Java集合列表

如何复制Java集合列表,java,list,collections,copy,Java,List,Collections,Copy,我有一个ArrayList,我想准确地复制它。如果可能的话,我会使用实用程序类,前提是有人花了一些时间来纠正它。因此,很自然地,我最终得到了Collections类,它包含一个copy方法 假设我有以下几点: List<String> a = new ArrayList<String>(); a.add("a"); a.add("b"); a.add("c"); List<String> b = new ArrayList<String>(a.si

我有一个
ArrayList
,我想准确地复制它。如果可能的话,我会使用实用程序类,前提是有人花了一些时间来纠正它。因此,很自然地,我最终得到了
Collections
类,它包含一个copy方法

假设我有以下几点:

List<String> a = new ArrayList<String>();
a.add("a");
a.add("b");
a.add("c");
List<String> b = new ArrayList<String>(a.size());

Collections.copy(b,a);
List a=new ArrayList();
a、 添加(“a”);
a、 添加(“b”);
a、 添加(“c”);
列表b=新的ArrayList(a.size());
收藏。副本(b,a);
这失败了,因为它基本上认为
b
不够大,无法容纳
a
。是的,我知道
b
的尺寸为0,但现在应该足够大了,不是吗?如果我必须先填写
b
,那么
Collections.copy()
在我的脑海中就成了一个完全无用的函数。那么,除了编程一个复制函数(我现在要做)之外,还有什么合适的方法可以做到这一点吗?

只需执行以下操作:

List a = new ArrayList(); 
a.add("a"); 
a.add("b"); 
a.add("c"); 
List b = new ArrayList(a);
ArrayList具有一个构造函数,该构造函数将接受另一个集合来从

b
复制元素,其容量为3,但大小为0。
ArrayList
具有某种缓冲区容量这一事实是一个实现细节-它不是
List
接口的一部分,因此
Collections.copy(List,List)
不使用它。如果它使用特殊情况
ArrayList
,那就太难看了

正如MrWiggles所指出的那样,在所提供的示例中,使用接受集合的ArrayList构造函数是实现此目的的方法


对于更复杂的场景(可能包括您的真实代码),您可能会发现其中的集合很有用。

复制列表的最简单方法是将其传递给新列表的构造函数:

List<String> b = new ArrayList<>(a);

如果要复制ArrayList,请使用以下命令进行复制:

List b = new ArrayList();
b.add("aa");
b.add("bb");

List a = new ArrayList(b);
不设置大小。它设置初始容量(即在需要调整大小之前可以容纳多少个元素)。在这种情况下,一种更简单的复制方式是:

List b = new ArrayList(a);

如果您设想将一些值复制到现有集合中的用例,那么复制并不是无用的。即,您希望覆盖现有元素而不是插入

例如:a=[1,2,3,4,5]b=[2,2,2,3,3,3,3,3,4,4,4,]a.copy(b)=[1,2,3,4,5,3,3,3,4,4,4]

但是,我希望有一个copy方法,它将为源集合和目标集合的开始索引获取额外的参数,并为count获取一个参数

请参见Java错误调用

List<String> b = new ArrayList<String>(a);
还可以在
b
中创建
a
的浅拷贝。如果第一个参数
b
没有足够的容量(而不是大小)来包含
a
的所有元素,那么它将抛出
索引自动边界异常。我们的期望是,不需要任何分配来工作,如果需要,则抛出该异常。要求对复制的集合进行预分配(
b
)是一种优化,但我通常认为该功能不值得,因为考虑到基于构造函数的替代方案(如上图所示,没有奇怪的副作用)所需的检查

要创建深度副本,
列表
,无论是通过哪种机制,都必须对底层类型有复杂的了解。对于
String
s,它在Java(以及.NET)中是不可变的,您甚至不需要深度拷贝。对于
MySpecialObject
,您需要知道如何对其进行深度复制,而这不是一般操作



注:最初接受的答案是
集合的最高结果。在谷歌中复制
,正如评论中指出的那样,它是完全错误的。

斯蒂芬·卡图尔卡(接受的答案)的答案是错误的(第二部分)。 它解释了
Collections.copy(b,a)执行深度复制,但它不执行。两者,
newarraylist(a)
集合。副本(b,a)仅进行浅层复制。不同之处在于,构造函数分配新内存,而
copy(…)
不分配,这使得它适用于可以重用阵列的情况,因为它在那里具有性能优势

Java标准API试图阻止深度副本的使用,因为如果新的编码人员定期使用深度副本,这将是不好的,这也可能是默认情况下
clone()
不公开的原因之一

Collections.copy(…)
的源代码可在第552行的以下位置查看:


如果需要深度复制,则必须在每个对象上使用for循环和clone()手动迭代项。

可以使用

List<String> b = new ArrayList<String>(a);
List b=新的数组列表(a);

因为它们是不可变的。除-->之外的每一个对象都需要自己迭代和复制。

正如hoijui提到的那样。从Stephen Katulka选择的答案包含有关Collections.copy的注释,该注释不正确。作者可能接受了它,因为第一行代码是他想要的副本。对Collections.copy的附加调用将再次复制。(导致复制发生两次)

下面是证明它的代码

public static void main(String[] args) {

    List<String> a = new ArrayList<String>();
    a.add("a");
    a.add("b");
    a.add("c");
    List<String> b = new ArrayList<String>(a);

    System.out.println("There should be no output after this line.");

    // Note, b is already a shallow copy of a;
    for (int i = 0; i < a.size(); i++) {
        if (a.get(i) != b.get(i)) {
            System.out.println("Oops, this was a deep copy."); // Note this is never called.
        }
    }

    // Now use Collections.copy and note that b is still just a shallow copy of a
    Collections.copy(b, a);
    for (int i = 0; i < a.size(); i++) {
        if (a.get(i) != b.get(i)) {
            System.out.println("Oops, i was wrong this was a deep copy"); // Note this is never called.
        }
    }

    // Now do a deep copy - requires you to explicitly copy each element
    for (int i = 0; i < a.size(); i++) {
        b.set(i, new String(a.get(i)));
    }

    // Now see that the elements are different in each 
    for (int i = 0; i < a.size(); i++) {
        if (a.get(i) == b.get(i)) {
            System.out.println("oops, i was wrong, a shallow copy was done."); // note this is never called.
        }
    }
}
publicstaticvoidmain(字符串[]args){
列表a=新的ArrayList();
a、 添加(“a”);
a、 添加(“b”);
a、 添加(“c”);
列表b=新阵列列表(a);
System.out.println(“此行之后应该没有输出”);
//注意,b已经是a的浅拷贝;
对于(int i=0;i// note: instantiating with a.size() gives `b` enough capacity to hold everything
List<String> b = new ArrayList<String>(a.size());
Collections.copy(b, a);
List<String> b = new ArrayList<String>(a);
public static void main(String[] args) {

    List<String> a = new ArrayList<String>();
    a.add("a");
    a.add("b");
    a.add("c");
    List<String> b = new ArrayList<String>(a);

    System.out.println("There should be no output after this line.");

    // Note, b is already a shallow copy of a;
    for (int i = 0; i < a.size(); i++) {
        if (a.get(i) != b.get(i)) {
            System.out.println("Oops, this was a deep copy."); // Note this is never called.
        }
    }

    // Now use Collections.copy and note that b is still just a shallow copy of a
    Collections.copy(b, a);
    for (int i = 0; i < a.size(); i++) {
        if (a.get(i) != b.get(i)) {
            System.out.println("Oops, i was wrong this was a deep copy"); // Note this is never called.
        }
    }

    // Now do a deep copy - requires you to explicitly copy each element
    for (int i = 0; i < a.size(); i++) {
        b.set(i, new String(a.get(i)));
    }

    // Now see that the elements are different in each 
    for (int i = 0; i < a.size(); i++) {
        if (a.get(i) == b.get(i)) {
            System.out.println("oops, i was wrong, a shallow copy was done."); // note this is never called.
        }
    }
}
public class User implements Serializable, Cloneable {

    private static final long serialVersionUID = 1L;

    private String user;
    private String password;
    ...

    @Override
    public Object clone() {
        Object o = null;
        try {
          o = super.clone();
        } catch(CloneNotSupportedException e) {
        }
        return o;
     }
 }
  public static void main(String[] args) {

      List<User> userList1 = new ArrayList<User>();

      User user1 = new User();
      user1.setUser("User1");
      user1.setPassword("pass1");
      ...

      User user2 = new User();
      user2.setUser("User2");
      user2.setPassword("pass2");
      ...

      userList1 .add(user1);
      userList1 .add(user2);

      List<User> userList2 = new ArrayList<User>();


      for(User u: userList1){
          u.add((User)u.clone());
      }

      //With this you can avoid 
      /*
        for(User u: userList1){
            User tmp = new User();
            tmp.setUser(u.getUser);
            tmp.setPassword(u.getPassword);
            ...
            u.add(tmp);               
        }
       */

  }
    List a = new ArrayList();
         a.add("1");
         a.add("abc");

    List b = b.addAll(listA);

//b will be 1, abc
List a = new ArrayList();
     a.add("1");
     a.add("abc");

List b = new ArrayList();
     b.add("x");
     b.addAll(listA);
     b.add("Y");

//b will be x, 1, abc, Y
List<String> b = Lists.newArrayList(a);
Copy [1, 2, 3] to [1, 2, 3] using copy constructor.

Copy [1, 2, 3] to (smaller) [4, 5]
java.lang.IndexOutOfBoundsException: Source does not fit in dest
        at java.util.Collections.copy(Collections.java:556)
        at com.farenda.java.CollectionsCopy.copySourceToSmallerDest(CollectionsCopy.java:36)
        at com.farenda.java.CollectionsCopy.main(CollectionsCopy.java:14)

Copy [1, 2] to (same size) [3, 4]
source: [1, 2]
destination: [1, 2]

Copy [1, 2] to (bigger) [3, 4, 5]
source: [1, 2]
destination: [1, 2, 5]

Copy [1, 2] to (unmodifiable) [4, 5]
java.lang.UnsupportedOperationException
        at java.util.Collections$UnmodifiableList.set(Collections.java:1311)
        at java.util.Collections.copy(Collections.java:561)
        at com.farenda.java.CollectionsCopy.copyToUnmodifiableDest(CollectionsCopy.java:68)
        at com.farenda.java.CollectionsCopy.main(CollectionsCopy.java:20)
private List<Item> cloneItemList(final List<Item> items)
    {
        Item[] itemArray = new Item[items.size()];
        itemArray = items.toArray(itemArray);
        return Arrays.asList(itemArray);
    }
List<String> b = Optional.ofNullable(a)
                         .map(list -> (List<String>) new ArrayList<>(list))
                         .orElseGet(Collections::emptyList);
List<String> b = Optional.ofNullable(a)
                         .map(List::stream)
                         .orElseGet(Stream::empty)
                         .collect(Collectors.toList())