在以下代码中:
static void findSubsets (ArrayList<Integer> numbers, int amount, int index)
{
ArrayList <Integer> numbersCopy = new ArrayList<Integer>(numbers.size());
Collections.copy(numbersCopy, numbers);
}
我收到了错误:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Source does not fit in dest
at java.util.Collections.copy(Collections.java:548)
at backtracking2.Main.findSubsets(Main.java:61)
为什么?
答案 0 :(得分:77)
容量不等于大小。您传入的size参数只是为该大小分配了足够的内存。它实际上并没有定义元素。这实际上是Collections.copy
的愚蠢要求,但它仍然是一个。
Collections.copy
JavaDocs的关键部分:
目的地列表必须至少与源列表一样长。如果它更长,则目标列表中的其余元素不受影响。
您应该将List
传递给ArrayList
的构造函数,以复制所有List
以完全避免此问题。
答案 1 :(得分:18)
这是一个非常好的问题,它几乎肯定与设置集合容量不一定分配底层对象这一事实有关,但为什么你这样做只是:
ArrayList <Integer> numbersCopy = new ArrayList<Integer>(numbers);
答案 2 :(得分:3)
构造函数ArrayList(Collection<? extends E> c)
会将c
中的每个元素复制到新创建的实例中,从而将numbers
复制到numbersCopy
。它也与numbersCopy.addAll(numbers)
相同,这正是你所需要的。
Collection.copy
要求dest
数组足够大以容纳source
数组中的所有元素,这是有道理的。类似的比喻是C函数memcpy
等。
答案 3 :(得分:1)
在创建ArrayList
并使用ArrayList
方法复制另一个Collections.copy()
的同时,我们需要确保目标List
包含相同数量的值(不只是相同大小) )作为来源List
。例如,如果源ArrayList
的值为[Red,Blue,Green],则目标ArrayList
也应包含相同数量的元素,例如[Orange,Yellow,Blue]。如果我们创建{{ 1}}的大小与源ArrayList
的大小相同,它将产生ArrayList
异常。
答案 4 :(得分:1)
您也可以使用Collections.addAll
像假设我们需要将List1复制到List2,然后
import java.util.Map;
import java.util.HashMap;
import java.util.UUID;
...
private static class UserInfo { // Nested class
public final User user;
public final int aux1;
public final String aux2;
public UserInfo(User user, int aux1, String aux2) {
this.user = user;
this.aux1 = aux1;
this.aux2 = aux2;
}
}
...
Map<UUID, UserInfo> main = new HashMap<UUID, UserInfo>();
在这里将添加文件,如果您想提高效率,请确保在添加list1之前清除list2,如下所示,
List2.addAll(List1);
答案 5 :(得分:-1)
在Java 8 +
中List<Integer> numbersCopy = numbers.stream().collect(Collectors.toList());
在Java 10+中更容易
List<Integer> numbersCopy = List.copyOf(numbers);
列表.copyOf()
返回包含给定集合元素的unmodifiable
列表。