如何复制 Java 集合列表

2022-08-31 07:38:05

我有一个,我想完全复制它。如果可能的话,我会使用实用程序类,前提是有人花了一些时间纠正它。所以很自然地,我最终得到了一个包含复制方法的类。ArrayListCollections

假设我有以下内容:

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

这失败了,因为基本上它认为不够大,无法容纳 。是的,我知道有0号,但它现在应该足够大,不是吗?如果我必须先填补,那么在我的脑海中就变成了一个完全无用的功能。那么,除了编写复制函数(我现在要这样做)之外,有没有合适的方法来做到这一点?babbCollections.copy()


答案 1

b容量为 3,但大小为 0。具有某种缓冲容量的事实是一个实现细节 - 它不是接口的一部分,因此不使用它。对于它的特殊情况来说,这将是丑陋的。ArrayListListCollections.copy(List, List)ArrayList

正如 tddmonkey 所指出的,使用采用集合的 ArrayList 构造函数是提供的示例中的方法。

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


答案 2

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

创建 内 的浅层副本。所有元素将以与它们所处的完全相同的顺序存在于其中(假设它有一个顺序)。abba

同样,调用

// note: instantiating with a.size() gives `b` enough capacity to hold everything
List<String> b = new ArrayList<String>(a.size());
Collections.copy(b, a);

还会创建 内 的浅副本。如果第一个参数 , 没有足够的容量(不是 size)来包含所有 的元素,那么它将抛出一个 。预期是 Collections.copy 不需要任何分配即可工作,如果有任何分配,则会引发该异常。要求对复制的集合进行预分配是一种优化(),但我通常不认为该功能是值得的,因为考虑到基于构造函数的替代方案(如上所示的替代方案)进行了必要的检查,这些替代方案没有奇怪的副作用。abbaIndexOutOfBoundsExceptionb

要创建深度副本,通过任一机制,都必须对底层类型有复杂的了解。对于在 Java 中不可变的 s(以及 .NET),您甚至不需要深度副本。在 的情况下,您需要知道如何制作它的深层副本,这不是一个泛型操作。ListStringMySpecialObject


注意:最初接受的答案是Google中的最高结果,正如评论中指出的那样,这是完全错误的。Collections.copy