如何将java.util.List复制到另一个java.util.List


135

我有一个List<SomeBean>从Web服务填充的。我想将该列表的内容复制/克隆到相同类型的空列表中。谷歌搜索复制列表建议我使用Collections.copy()方法。在我看到的所有示例中,目标列表应该包含要进行复制的确切项目数。

由于我正在使用的列表是通过Web服务填充的,并且其中包含数百个对象,因此我无法使用上述技术。还是我用错了?无论如何,为了使其正常工作,我试图做这样的事情,但是我仍然得到了IndexOutOfBoundsException

List<SomeBean> wsList = app.allInOne(template);

List<SomeBean> wsListCopy=new ArrayList<SomeBean>(wsList.size());   
Collections.copy(wsListCopy,wsList);
System.out.println(wsListCopy.size());

我尝试使用,wsListCopy=wsList.subList(0, wsList.size())ConcurrentAccessException后来在代码中找到了。命中和审判。:)

无论如何,我的问题很简单,如何将列表的全部内容复制到另一个列表中?当然,不是通过迭代。


11
当然,任何副本都将使用迭代。您可以将其隐藏起来,但仍会存在。
彼得·劳瑞

1
首先:确定要复制该列表吗?您这样做的动机是什么?
ppeterka

2
是的,迭代只是隐藏在该层之下。但是添加了注释是为了防止出现任何迭代答案。:)
Mono Jamoon

@ppeterka我正在执行列表中的操作,如removeAll()。这将导致列表丢失其原始数据。之后,还需要“该数据”。
Mono Jamoon

返回的列表的实际类型是app.allInOne(template)什么?ArrayList
Andremoniy 2013年

Answers:


235

只需使用此:

List<SomeBean> newList = new ArrayList<SomeBean>(otherList);

注意:仍然不是线程安全的,例如,如果您otherList从另一个线程进行修改,则可能要使其otherList(甚至newList)成为a CopyOnWriteArrayList,或者使用锁定原语(例如ReentrantReadWriteLock)对对任何列表的读/写访问进行序列化并发访问。


1
现在,我真的觉得自己很愚蠢:)我希望这样构造它不会抛出任何错误ConcurrentAccessException
Mono Jamoon 2013年


5
如果他得到ConcurrentModifcationException,则+1,他有一个并发问题,需要首先解决。
彼得·劳瑞

5
如果问题提到“复制/克隆”,为什么这个答案会得到这么多积分?只要其他一些答案与克隆无关。无论您使用哪种集合/流特定的实用程序方法,都将为集合内的对象保留相同的引用。
yuranos

3
答案是错误的。内容未复制。仅它是参考。
令人难以置信的

33

这是一种非常不错的Java 8方法:

List<String> list2 = list1.stream().collect(Collectors.toList());

当然,这里的优点是您可以过滤并跳至仅列表的一部分副本。

例如

//don't copy the first element 
List<String> list2 = list1.stream().skip(1).collect(Collectors.toList());

4
结果列表是原始列表的深拷贝还是浅拷贝?
Infinitum Ad

7
浅表副本。
kap

3
不幸的是,这也不是线程安全的。假设list在收集器运行时进行了更改,ConcurrentModificationException则会抛出a。
C-Otto

@Dan,如何跳过复制最后一个元素?
CKM

@chandresh跳过复制最后一个元素的步骤,您只需使用.limit(list1.size() - 1)
Matthew Carpenter

13
originalArrayList.addAll(copyArrayofList);

每当使用addAll()方法进行复制时,请记住,对同一对象的两个数组列表(originalArrayList和copyArrayofList)引用的内容都将添加到列表中,因此,如果您修改其中的任何一个,那么copyArrayofList也会反映相同的变化。

如果您不想产生副作用,则需要将每个元素从originalArrayList复制到copyArrayofList,例如使用for或while循环。


2
这是这里为数不多的真正答案之一,因为它指定了#addAll进行浅表复制以及如何进行深表复制。更多详细信息: stackoverflow.com/questions/715650/…–
cellepo

7

我试图做这样的事情,但是我仍然得到了IndexOutOfBoundsException。

我有一个ConcurrentAccessException

这意味着您在尝试复制列表时正在修改列表,很可能是在另一个线程中进行的。要解决此问题,您必须

  • 使用专为并发访问而设计的集合。

  • 适当地锁定集合,以便您可以对其进行迭代(或允许您调用为您执行此操作的方法)

  • 找个地方,避免需要复制原始列表。



3

Java 8还有另一种以空安全的方法。

List<SomeBean> wsListCopy = Optional.ofNullable(wsList)
                                    .map(List::stream)
                                    .orElseGet(Stream::empty)
                                    .collect(Collectors.toList());

如果要跳过一个元素。

List<SomeBean> wsListCopy = Optional.ofNullable(wsList)
                                    .map(List::stream)
                                    .orElseGet(Stream::empty)
                                    .skip(1)
                                    .collect(Collectors.toList());

1

我遇到了相同的问题ConcurrentAccessException,而mysolution是:

List<SomeBean> tempList = new ArrayList<>();

for (CartItem item : prodList) {
  tempList.add(item);
}
prodList.clear();
prodList = new ArrayList<>(tempList);

因此,它一次只能执行一项操作,并且避免了Exeption ...


1

我尝试了类似的操作,并且能够重现该问题(IndexOutOfBoundsException)。以下是我的发现:

1)Collections.copy(destList,sourceList)的实现首先通过调用size()方法检查目标列表的大小。由于对size()方法的调用将始终返回列表中的元素数(在这种情况下为0),因此构造函数ArrayList(capacity)仅确保支持数组的初始容量,而与后备数组没有任何关系。列表的大小。因此,我们总是得到IndexOutOfBoundsException。

2)一种相对简单的方法是使用以集合为参数的构造函数:

List<SomeBean> wsListCopy=new ArrayList<SomeBean>(wsList);  

0

indexOutOfBoundsException回复:,您的子列表参数是问题;您需要以大小1结束子列表。由于从零开始,列表的最后一个元素始终为size-1,在size位置没有元素,因此会出现错误。




-2

如果您不希望一个列表中的更改影响另一个列表,请尝试此方法。它对我有用。希望对您有所
帮助。

  public class MainClass {
  public static void main(String[] a) {

    List list = new ArrayList();
    list.add("A");

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

    System.out.println(list);
    System.out.println(list2);

    list.clear();

    System.out.println(list);
    System.out.println(list2);
  }
}

> Output:   
[A]  
[A]  
[]  
[A]

-3

subList函数是一个技巧,返回的对象仍在原始列表中。因此,如果您在subList中执行任何操作,无论是单线程还是多线程,都会在代码中导致并发异常。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.