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);

    在這裡,我們只是將源列表傳遞給目標列表的構造函數,目的列表將創建源列表的淺表副本。

    目標列表將只是對源列表引用的同一對象的另一個引用。因此,任何引用所做的每次更改都會影響同一對象。

    因此,使用構造函數是複制不可變對象(如IntegersStrings. )的好選擇Strings.

    4.3。 addAll

    另一種簡單的方法是使用ListaddAll方法:

    List<Integer> destination = new ArrayList<>();
    
     destination.addAll(source);

    The addAll方法會將源列表的所有元素複製到目標列表。

    關於此方法,有幾點要注意:

    1. 它創建源列表的淺表副本。
    2. 源列表的元素將附加到目標列表。

    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.