简体   繁体   English

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

[英]How to copy a java.util.List into another java.util.List

I have a List<SomeBean> that is populated from a Web Service.我有一个从 Web 服务填充的List<SomeBean> I want to copy/clone the contents of that list into an empty list of the same type.我想将该列表的内容复制/克隆到相同类型的空列表中。 A Google search for copying a list suggested me to use Collections.copy() method.用于复制列表的 Google 搜索建议我使用Collections.copy()方法。 In all the examples I saw, the destination list was supposed to contain the exact number of items for the copying to take place.在我看到的所有示例中,目标列表应该包含要进行复制的确切项目数。

As the list I am using is populated through a web service and it contains hundreds of objects, I cannot use the above technique.由于我正在使用的列表是通过 Web 服务填充的,并且它包含数百个对象,因此我无法使用上述技术。 Or I am using it wrong??!!还是我用错了??!! Anyways, to make it work, I tried to do something like this, but I still got an IndexOutOfBoundsException .无论如何,为了让它工作,我尝试做这样的事情,但我仍然得到一个IndexOutOfBoundsException

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

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

I tried to use the wsListCopy=wsList.subList(0, wsList.size()) but I got a ConcurrentAccessException later in the code.我尝试使用wsListCopy=wsList.subList(0, wsList.size())但后来在代码中得到了ConcurrentAccessException Hit and trial.打击和审判。 :) :)

Anyways, my question is simple, how can I copy the entire content of my list into another List?无论如何,我的问题很简单,如何将列表的全部内容复制到另一个列表中? Not through iteration, of course.当然,不是通过迭代。

Just use this:只需使用这个:

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

Note: still not thread safe, if you modify otherList from another thread, then you may want to make that otherList (and even newList ) a CopyOnWriteArrayList , for instance -- or use a lock primitive, such as ReentrantReadWriteLock to serialize read/write access to whatever lists are concurrently accessed.注意:仍然不是线程安全的,如果您从另一个线程修改otherList ,那么您可能希望将该otherList (甚至newList )设置为CopyOnWriteArrayList ,例如 - 或使用锁定原语,如ReentrantReadWriteLock序列化读/写访问到同时访问的任何列表。

This is a really nice Java 8 way to do it:这是一种非常好的 Java 8 方法:

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

Of course the advantage here is that you can filter and skip to only copy of part of the list.当然,这里的好处是您可以过滤并仅跳转到列表的一部分副本。

eg例如

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

Please keep on mind whenever using the addAll() method for copy, the contents of both the array lists (originalArrayList and copyArrayofList) references to the same objects will be added to the list so if you modify any one of them then copyArrayofList also will also reflect the same change.请记住,每当使用addAll()方法进行复制时,对相同对象的两个数组列表(originalArrayList 和 copyArrayofList)引用的内容都将添加到列表中,因此如果您修改其中任何一个,则 copyArrayofList 也将反映相同的变化。

If you don't want side effect then you need to copy each of element from the originalArrayList to the copyArrayofList, like using a for or while loop.如果您不想要副作用,那么您需要将每个元素从 originalArrayList 复制到 copyArrayofList,例如使用 for 或 while 循环。 for deep copy you can use below code snippet.对于深拷贝,您可以使用下面的代码片段。

but one more thing you need to do, implement the Cloneable interface and override the clone() method for SomeBean class.但是您还需要做一件事,实现Cloneable接口并覆盖 SomeBean 类的clone()方法。

public static List<SomeBean> cloneList(List<SomeBean> originalArrayList) {
    List<SomeBean> copyArrayofList = new ArrayList<SomeBean>(list.size());
    for (SomeBean item : list) copyArrayofList.add(item.clone());
    return copyArrayofList;
}

I tried to do something like this, but I still got an IndexOutOfBoundsException.我试图做这样的事情,但我仍然得到一个 IndexOutOfBoundsException。

I got a ConcurrentAccessException我有一个 ConcurrentAccessException

This means you are modifying the list while you are trying to copy it, most likely in another thread.这意味着您在尝试复制列表时正在修改列表,很可能是在另一个线程中。 To fix this you have to either要解决此问题,您必须

  • use a collection which is designed for concurrent access.使用专为并发访问而设计的集合。

  • lock the collection appropriately so you can iterate over it (or allow you to call a method which does this for you)适当地锁定集合,以便您可以对其进行迭代(或允许您调用为您执行此操作的方法)

  • find a away to avoid needing to copy the original list.找一个地方避免需要复制原始列表。

Starting from Java 10 :Java 10开始:

List<E> oldList = List.of();
List<E> newList = List.copyOf(oldList);

List.copyOf() returns an unmodifiable List containing the elements of the given Collection . List.copyOf()返回一个不可修改的List包含给定Collection的元素。

The given Collection must not be null , and it must not contain any null elements.给定的Collection不得为null ,并且不得包含任何null元素。

Also, if you want to create a deep copy of a List , you can find many good answers here .此外,如果您想创建List的深层副本,您可以在此处找到许多好的答案。

There is another method with Java 8 in a null-safe way. Java 8 还有另一种方法是空安全的。

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

If you want to skip one element.如果你想跳过一个元素。

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

With Java 9+, the stream method of Optional can be used Java 9+ 可以使用 Optional 的 stream 方法

Optional.ofNullable(wsList)
    .stream()
    .flatMap(Collection::stream)
    .collect(Collectors.toList())

I tried something similar and was able to reproduce the problem (IndexOutOfBoundsException).我尝试了类似的方法并且能够重现问题(IndexOutOfBoundsException)。 Below are my findings:以下是我的发现:

1) The implementation of the Collections.copy(destList, sourceList) first checks the size of the destination list by calling the size() method. 1) Collections.copy(destList, sourceList) 的实现首先通过调用size() 方法检查目标列表的大小。 Since the call to the size() method will always return the number of elements in the list (0 in this case), the constructor ArrayList(capacity) ensures only the initial capacity of the backing array and this does not have any relation to the size of the list.由于对 size() 方法的调用将始终返回列表中的元素数(在本例中为 0),因此构造函数 ArrayList(capacity) 仅确保后备数组的初始容量,这与列表的大小。 Hence we always get IndexOutOfBoundsException.因此,我们总是得到 IndexOutOfBoundsException。

2) A relatively simple way is to use the constructor that takes a collection as its argument: 2) 一种相对简单的方法是使用以集合为参数的构造函数:

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

I was having the same problem ConcurrentAccessException and mysolution was to:我遇到了同样的问题ConcurrentAccessException ,我的解决方案是:

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

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

So it works only one operation at the time and avoids the Exeption...所以它一次只工作一个操作,避免了 Exeption ......

You can use addAll().您可以使用 addAll()。

eg : wsListCopy.addAll(wsList);例如: wsListCopy.addAll(wsList);

re: indexOutOfBoundsException , your sublist args are the problem;回复: indexOutOfBoundsException ,您的子列表参数是问题所在; you need to end the sublist at size-1.您需要以 size-1 结束子列表。 Being zero-based, the last element of a list is always size-1, there is no element in the size position, hence the error.从零开始,列表的最后一个元素总是大小为 1,大小位置没有元素,因此错误。

I can't see any correct answer.我看不到任何正确的答案。 If you want a deep copy you have to iterate and copy object manually (you could use a copy constructor).如果你想要一个深拷贝,你必须手动迭代和复制对象(你可以使用复制构造函数)。

You should use the addAll method.您应该使用addAll方法。 It appends all of the elements in the specified collection to the end of the copy list.它将指定集合中的所有元素附加到副本列表的末尾。 It will be a copy of your list.这将是您的清单的副本。

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

just in case you use Lombok:以防万一您使用龙目岛:

mark SomeBean with the following annotation:使用以下注释标记 SomeBean:

@Builder(toBuilder = true, builderMethodName = "")

and Lombok will perform a shallow copy of objects for you using copy constructor: Lombok 将使用复制构造函数为您执行对象的浅拷贝:

inputList.stream()
         .map(x -> x.toBuilder().build())
         .collect(Collectors.toList());

使用 list new ArrayList<>(list) 的内置构造函数

"

I have a List<SomeBean> that is populated from a Web Service.我有一个从Web服务填充的List<SomeBean> I want to copy/clone the contents of that list into an empty list of the same type.我想将该列表的内容复制/克隆到相同类型的空列表中。 A Google search for copying a list suggested me to use Collections.copy() method.谷歌搜索复制列表建议我使用Collections.copy()方法。 In all the examples I saw, the destination list was supposed to contain the exact number of items for the copying to take place.在我看到的所有示例中,目标列表都应该包含要进行复制的确切项目数。

As the list I am using is populated through a web service and it contains hundreds of objects, I cannot use the above technique.由于我正在使用的列表是通过Web服务填充的,并且其中包含数百个对象,因此我无法使用上述技术。 Or I am using it wrong??!!还是我用错了?? Anyways, to make it work, I tried to do something like this, but I still got an IndexOutOfBoundsException .无论如何,为了使其正常工作,我试图做这样的事情,但是我仍然得到了IndexOutOfBoundsException

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

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

I tried to use the wsListCopy=wsList.subList(0, wsList.size()) but I got a ConcurrentAccessException later in the code.我尝试使用wsListCopy=wsList.subList(0, wsList.size())但稍后在代码中得到了ConcurrentAccessException Hit and trial.命中和审判。 :) :)

Anyways, my question is simple, how can I copy the entire content of my list into another List?无论如何,我的问题很简单,如何将列表的全部内容复制到另一个列表中? Not through iteration, of course.当然,不是通过迭代。

subList function is a trick, the returned object is still in the original list. subList 函数是一个技巧,返回的对象仍然在原始列表中。 so if you do any operation in subList, it will cause the concurrent exception in your code, no matter it is single thread or multi thread.所以如果你在 subList 中进行任何操作,无论是单线程还是多线程,都会导致代码中的并发异常。

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

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