2011-05-27 88 views
55

在下面的代碼:java.lang.IndexOutOfBoundsException:源不適合在dest

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) 

爲什麼?

回答

71

容量不等。您傳入的大小參數只是爲該大小分配足夠的內存。它實際上並沒有定義元素。這實際上是Collections.copy的一個愚蠢的要求,但它仍然是一個。

的關鍵部分來自Collections.copy JavaDocs

The destination list must be at least as long as the source list. If it is longer, the remaining elements in the destination list are unaffected.

你應該只通過ListArrayList的構造複製所有List的完全避免這個問題。

+2

我降低了這一點,因爲將它添加到構造函數將執行[b]淺[/ b]副本並且不會與深度副本相同。操縱原始列表中的元素,也將在「複製到」列表中操作它們 – Boy 2014-11-29 13:12:29

+2

@Boy您的觀點不正確。查看[ArrayList源代碼](http://hg.openjdk.java.net/jdk7/modules/jdk/file/a37326fa7f95/src/share/classes/java/util/ArrayList.java#l150),其中深層copy_of_list_是通過調用'toArray'和['Arrays.copyOf'](https://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#copyOf( U [],%20int,%20java.lang.Class))。 'numbersCopy = new ArrayList (numbers)'後對列表所做的更改不影響另一個。這肯定會破壞構造函數的目的(並且無論如何它都需要一個'Collection'而不是'List')。 – pickypg 2014-12-01 02:07:19

+1

@Boy除非你知道_elements本身並沒有被重構爲一個真正的深層拷貝?由於Java不需要拷貝構造函數,這是幾乎不可能的要求,['Collections.copy'也不執行](http://hg.openjdk.java.net/jdk7/modules/jdk/file/ a37326fa7f95/SRC /共享/類/爪哇/ util的/ Collections.java#l545)。 – pickypg 2014-12-01 02:10:43

14

這是一個非常好的問題,它幾乎可以肯定有一個事實,即設定一個集合能力不一定分配基礎對象的事,但你爲什麼做這樣的說法時,你可以:

ArrayList <Integer> numbersCopy = new ArrayList<Integer>(numbers); 
+2

它複製引用 – temirbek 2017-07-20 11:55:17

3

構造ArrayList(Collection<? extends E> c)將從c每個元素複製到新創建的實例,從而複製numbersnumbersCopy。這與numbersCopy.addAll(numbers)一樣,這實際上是你所需要的。

確實有意義的是,Collection.copy要求dest陣列足夠大以容納source陣列中的所有元素。類似的類比是C函數memcpy等。