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.
0 评论