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

时间:2013-01-14 13:52:50

标签: java collections copy

我有一个从Web服务填充的List<SomeBean>。我想将该列表的内容复制/克隆到相同类型的空列表中。谷歌搜索复制列表建议我使用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。命中和审判。 :)

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

14 个答案:

答案 0 :(得分:214)

请使用:

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

注意:仍然不是线程安全的,如果你从另一个线程修改otherList,那么你可能想让otherList(甚至newList)成为CopyOnWriteArrayList,例如 - 或者使用一个锁原语,例如ReentrantReadWriteLock来序列化对同时访问的列表的读/写访问。

答案 1 :(得分:27)

这是一个非常好的Java 8方法:

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

当然,这里的优势在于您可以过滤并跳过仅列出部分列表的副本。

e.g。

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

答案 2 :(得分:11)

originalArrayList.addAll(copyArrayofList);

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

如果你不想要副作用,那么你需要将每个元素从originalArrayList复制到copyArrayofList,就像使用for或while循环一样。

答案 3 :(得分:7)

  

我试图做这样的事情,但我仍然有一个IndexOutOfBoundsException。

     

我收到了ConcurrentAccessException

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

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

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

  • 找一个离开以避免需要复制原始列表。

答案 4 :(得分:2)

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

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

如果你想跳过一个元素。

    string accessToken = GlobalSettings.userToken;
string addItemJsonString = "{\"fields\":{\"Title\":\"This is test record\"}}";
string requestUrl = "https://graph.microsoft.com/v1.0/sites/{site-id}/lists/{list-id}/items";

HttpClient client = new HttpClient();

HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, requestUrl);
message.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
message.Content = new StringContent(addItemJsonString, Encoding.UTF8, "application/json"); 
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
HttpResponseMessage response = await client.SendAsync(message);

答案 5 :(得分:2)

Java 10 开始:

List

List.copyOf()返回一个不可修改的Collection,其中包含给定Collection的元素。

指定的null不得为null,且不得包含任何List元素。

此外,如果您想创建{{1}}的深层副本,您可以找到许多好的答案here

答案 6 :(得分:1)

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

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

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

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

答案 7 :(得分:1)

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

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

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

因此它当时只能运行一个操作并避免执行...

答案 8 :(得分:0)

re:indexOutOfBoundsException,您的子列表是问题所在;你需要以size-1结束子列表。从零开始,列表的最后一个元素总是大小为1,大小位置中没有元素,因此错误。

答案 9 :(得分:0)

您可以使用addAll()。

例如:wsListCopy.addAll(wsList);

答案 10 :(得分:0)

我看不出任何正确答案。如果你想要一个深拷贝,你必须手动迭代和复制对象(你可以使用一个复制构造函数)。

答案 11 :(得分:0)

您应该使用addAll方法。它将指定集合中的所有元素附加到副本列表的末尾。这将是您的列表的副本。

List<String> myList = new ArrayList<>();
myList.add("a");
myList.add("b");
List<String> copyList = new ArrayList<>();
copyList.addAll(myList);

答案 12 :(得分:-1)

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

  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]

答案 13 :(得分:-2)

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