Java IndexOutOfBoundsException: “Source Does Not Fit in Dest”
1.概述
在Java中,複製List
有時會產生IndexOutOfBoundsException: “Source does not fit in dest”.
在這個簡短的教程中,我們將研究為什麼使用Collections.copy
方法時會出現此錯誤,以及如何解決該錯誤。我們還將研究Collections.copy
替代方法,以製作列表的副本。
2.重現問題
讓我們從使用Collections.copy
方法創建List
副本的方法開始:
static List<Integer> copyList(List<Integer> source) {
List<Integer> destination = new ArrayList<>(source.size());
Collections.copy(destination, source);
return destination;
}
在這裡, copyList
方法創建一個新列表,其初始容量等於源列表的大小。然後,它嘗試將源列表的元素複製到目標列表:
List<Integer> source = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> copy = copyList(source);
但是,一旦調用copyList
方法,它就會引發異常java.lang.IndexOutOfBoundsException: Source does not fit in dest
。
3. Exception
原因
讓我們嘗試了解出了什麼問題。根據Collections.copy
方法的文檔:
目標列表必須至少與源列表一樣長。如果更長,則目標列表中的其餘元素不受影響。
在我們的示例中,我們使用構造函數創建了一個新List
,其初始容量等於源列表的大小。它只是分配足夠的內存,而實際上沒有定義元素。新列表的大小保持為零,因為容量和大小是List
不同屬性。
因此,當Collections.copy
方法嘗試將源列表複製到目標列表時,它將引發java.lang.IndexOutOfBoundsException.
4.解決方案
4.1。 Collections.copy
讓我們看一個使用Collections.copy
方法將List
複製到另一個List
的工作示例:
List<Integer> destination = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> source = Arrays.asList(11, 22, 33);
Collections.copy(destination, source);
在這種情況下,我們會將源列表的所有三個元素複製到目標列表。 Arrays.asList
方法使用元素(而不只是大小)初始化列表,因此,我們能夠成功地將源列表複製到目標列表。
如果僅交換Collections.copy
方法的參數,則它將拋出java.lang.IndexOutOfBoundsException
因為源列表的大小小於目標列表的大小.
執行此復制操作後,目標列表如下所示:
[11, 22, 33, 4, 5]
除了Collections.copy
方法外,Java中還有其他方法可以復制List
。讓我們看看其中的一些。
4.2。 ArrayList
構造函數
複製List
的最簡單方法是使用帶有Collection
參數的構造函數:
List<Integer> source = Arrays.asList(11, 22, 33);
List<Integer> destination = new ArrayList<>(source);
在這裡,我們只是將源列表傳遞給目標列表的構造函數,目的列表將創建源列表的淺表副本。
目標列表將只是對源列表引用的同一對象的另一個引用。因此,任何引用所做的每次更改都會影響同一對象。
因此,使用構造函數是複制不可變對象(如Integers
和Strings.
)的好選擇Strings.
4.3。 addAll
另一種簡單的方法是使用List
的addAll
方法:
List<Integer> destination = new ArrayList<>();
destination.addAll(source);
The addAll
方法會將源列表的所有元素複製到目標列表。
關於此方法,有幾點要注意:
- 它創建源列表的淺表副本。
- 源列表的元素將附加到目標列表。
4.4。 Java 8 Streams
Java 8引入了Stream API,它是使用Java Collections.
的出色工具Collections.
使用stream()
方法,我們使用Stream API複製列表:
List<Integer> copy = source.stream()
.collect(Collectors.toList());
4.5。 Java 10
在Java 10中,複製List
甚至更簡單。使用copyOf()
方法允許我們創建一個包含給定Collection
元素的不可變列表:
List<Integer> destination = List.copyOf(sourceList);
如果要採用這種方法,則需要確保輸入List
不為null
,並且其中不包含任何null
元素。
5.結論
在本文中,我們研究了Collections.copy
方法如何以及為什麼引發IndexOutOfBoundException “Source does not file in dest”
。隨之,我們還探索了將List
複製到另一個List.
不同方法List.