我有一个从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
。命中和审判。 :)
无论如何,我的问题很简单,如何将列表的整个内容复制到另一个列表?当然不是通过迭代。
答案 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中执行任何操作,它将导致代码中的并发异常,无论它是单线程还是多线程。