在以下代码中:
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)
为什么?
容量不等于大小。您传入的size参数只是为该大小分配了足够的内存。它实际上并没有定义元素。这实际上是对Collections.copy
的愚蠢要求,但它仍然是一个。
来自Collections.copy
JavaDocs的关键部分:
目标列表必须至少与源列表一样长。如果它更长,则目标列表中的其余元素不受影响。
你应该将List
传递给ArrayList
的构造函数来复制所有的List
以完全避免这个问题。
这是一个非常好的问题,它几乎肯定与设置集合容量不一定分配底层对象这一事实有关,但是为什么你这样做当你可以:
ArrayList <Integer> numbersCopy = new ArrayList<Integer>(numbers);
构造函数ArrayList(Collection<? extends E> c)
会将c
中的每个元素复制到新创建的实例中,从而将numbers
复制到numbersCopy
中。它也和numbersCopy.addAll(numbers)
一样,这正是你所需要的。
有意义的是,Collection.copy
要求dest
数组足够大以容纳来自source
数组的所有元素。类似的类比是C函数memcpy
等。
在创建ArrayList
以使用ArrayList
方法复制另一个Collections.copy()
时,我们需要确保目标List
包含与源List
相同数量的值(不仅仅是相同大小)。例如,如果源ArrayList
具有值[红色,蓝色,绿色],那么目标ArrayList
也应该包含相同数量的元素,如[橙色,黄色,蓝色]。如果我们创建一个与源ArrayList
大小相同的ArrayList
,它会给OutOfBounds
例外。