![](/img/trans.png)
[英]Java ArrayList IndexOutOfBoundsException despite giving an initial capacity
[英]Java 8 ArrayList initial capacity broken?
今天,当我遇到一个奇怪的问题时,我正在考虑克隆一个 ArrayList。 我阅读了这个答案并尝试过。 但是,我收到了一个 ArrayOutOfBounds 异常。 所以我仔细研究了一下,似乎 ArrayList<>(int size) 不起作用?
这是一个已知问题吗?
测试类:
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
public class ArrayListTest {
@Test
public void test() {
List<String> lista = new ArrayList<>();
lista.add("a");
List<String> listb = new ArrayList<>(lista.size());
System.out.println("Size of lista: " + lista.size());
System.out.println("Size of listb: " + listb.size());
}
}
疑难班:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.junit.Test;
public class ArrayListTest2 {
@Test
public void test() {
List<String> lista = new ArrayList<>();
lista.add("a");
List<String> listb = new ArrayList<>(lista.size());
Collections.copy(listb, lista);
System.out.println("Lista: " + lista);
System.out.println("Listb: " + listb);
}
}
结果是:
java.lang.IndexOutOfBoundsException:源不适合目标
在 java.util.Collections.copy(Collections.java:556)
在 ArrayListTest2.test(ArrayListTest2.java:13)
有任何想法吗?
这确实是Collections.copy()
文档的问题。 它的JDK 8 文档说:
目标列表必须至少与源列表一样长。 如果它更长,则目标列表中的其余元素不受影响。
这使用了术语“长”和“更长”,它们似乎指的是列表的长度。 但是,如果您查看List
规范,则没有长度的定义——但是有size 的定义,在ArrayList
中有容量的定义。 目前还不清楚Collections.copy()
是根据列表的大小还是容量来定义的。
事实上, Collections.copy()
应该根据列表的大小来定义。 Collections.copy()
的JDK 9 规范已修改为:
目标列表的大小必须大于或等于源列表的大小。 如果它更大,则目标列表中的其余元素不受影响。
ArrayList
构造函数的 arg 设置它的初始容量,而不是它的大小。 大小是列表中当前存在的元素数。 Collections.copy()
要求目标列表的大小大于或等于源的大小。 这就是为什么当您尝试将大小为 1 的列表复制到大小为 0 的列表时会得到IndexOutOfBoundsException
的原因。
如果目标列表太小,我会抛出IndexOutOfBoundsException。
import java.util.*;
public class CollectionsDemo {
public static void main(String args[]) {
// create two lists
List<String> srclst = new ArrayList<String>(5);
List<String> destlst = new ArrayList<String>(10);
// populate two lists
srclst.add("a");
srclst.add("b");
srclst.add("d");
destlst.add("e");
destlst.add("f");
destlst.add("g");
// copy into dest list
Collections.copy(destlst, srclst);
System.out.println("Value of source list: "+srclst);
System.out.println("Value of destination list: "+destlst);
}
我认为您对initialCapacity
的理解存在问题。 就像当你初始化一个用“空”值填充的基元数组时,在ArrayList
的初始化过程中不会发生这样的事情。 通过将initialCapacity
设置为n
,您所做的就是让编译器知道它应该为n
对象分配足够的内存。 请注意,即使已分配内存,列表的大小仍为 0,因为其中没有元素。
关于copy()
。 您正在尝试将lista
复制到初始容量为lista.size() = 0
。 那里似乎没有什么不对劲的地方吗?
这种混淆可能是因为文档根本没有提到字size
,但这是这里的关键因素。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.