Java ArrayList初始容量和IndexOutOfBoundsException

Java ArrayList初始容量和IndexOutOfBoundsException,java,string,arraylist,Java,String,Arraylist,考虑以下示例代码: List<String> myList = new ArrayList<String>(7); myList.add(5, "Hello"); myList.removeAll(Collections.singleton(null)); System.out.println(myList.size() + " objects:" ); for (String s : myList) { System.out.println("\t" + s)

考虑以下示例代码:

List<String> myList = new ArrayList<String>(7);
myList.add(5, "Hello");
myList.removeAll(Collections.singleton(null));

System.out.println(myList.size() + " objects:" );
for (String s : myList) {
    System.out.println("\t" + s);
}
List myList=newarraylist(7);
添加(5,“你好”);
myList.removeAll(Collections.singleton(null));
System.out.println(myList.size()+“objects:”);
for(字符串s:myList){
System.out.println(“\t”+s);
}
myList
初始化为初始容量7,然后下一行尝试在位置5添加字符串“Hello”。这会引发IndexOutOfBoundsException:

线程“main”java.lang.IndexOutOfBoundsException中出现异常:索引:5,大小:0

我查看了“初始容量”在ArrayList中的含义。我知道这个特殊的构造函数为7个字符串元素分配了空间,如果我们尝试向列表中添加8个元素,它将不得不分配更多的空间

我不明白的是,为什么它不创建一个大小为7的“空”列表,每个索引处都有空值,类似于我们声明
String[]myArray=newstring[7]
时会发生的情况。我记得我了解到ArrayList是Java动态数组的实现,所以我期望类似的行为。如果我在声明
newarraylist(7)
时没有为7个字符串分配空间,那么实际发生了什么

我不明白的是,为什么它不创建一个大小为7的“空”列表,每个索引处都有空值,类似于我们声明String[]myArray=newstring[7]时会发生的情况

这在某些情况下会很有用。。。而且对其他人没有用处。通常情况下,您有一个要创建的列表大小的上限(或者至少是一个猜测),但随后您会填充它。。。你不想有一个列表,然后有错误的大小。。。因此,您必须在“设置”值时维护索引,然后再设置大小

我记得我了解到ArrayList是Java动态数组的实现,所以我期望类似的行为

不,真的不是。它是一个可以调整大小并在幕后使用数组的列表。尽量不要把它看作一个数组

如果我在声明新的
ArrayList(7)
时没有为7个字符串分配空间,那么实际发生了什么

您确实有7个字符串引用的空间。缓冲区大小(即容量)至少为7,但列表的逻辑大小仍然为0-您尚未向其中添加任何内容。就像你有一张纸,足够写7行,但是你还没有写任何东西

如果需要预填充列表,可以轻松编写方法来创建:

public static List<T> createPrefilledList(int size, T item) {
    ArrayList<T> list = new ArrayList<T>(size);
    for (int i = 0; i < size; i++) {
        list.add(item);
    }
    return list;
}
公共静态列表createPrefilledList(整数大小,T项){
ArrayList list=新的ArrayList(大小);
对于(int i=0;i
初始容量只做一件事:它给出了支持阵列应该有多大的建议(而不是要求)。从逻辑上讲,在有或没有建议的情况下,允许哪些操作,或者建议是什么,两者之间没有区别。唯一的变化将是作为优化建议可能发生或不发生的内部操作

您只能将这样的“添加”到阵列中已经存在的位置。位置5之前的元素还不存在,所以它抛出一个异常。从:

抛出: IndexOutOfBoundsException-如果索引超出范围(索引<0 | |索引>大小())


数组的初始容量与其大小之间存在差异(即数组包含的元素数)。它的大小用于确定您是否试图访问超出范围的索引

以下是执行此检查的方法:

 private void rangeCheckForAdd(int index) {
   if (index < 0 || index > this.size)
     throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
 }
private void rangeCheckForAdd(整数索引){
如果(索引<0 | |索引>此.size)
抛出新的IndexOutOfBoundsException(outOfBoundsMsg(index));
}

如您所见,它与阵列的初始容量无关。它完全基于它包含的元素数量。

这里的容量和大小是两个完全不同的东西。您需要添加7个占位符元素来执行您正在尝试的操作,而不仅仅是使用初始容量7
ArrayList
不是数组的替代品。另请参见查看源代码,Object[]elementDate=new Object[7];,这难道不意味着它应该有7个基于默认值prinicple的空元素(elementData是实例变量)?@thinkstip:我不确定你想表达什么观点,或者你在寻找什么来源。数组将有7个(不是8个)空值。但是列表的逻辑大小仍然是0。是的,7个空值,OP尝试在索引5处插入元素,这是具有空值的有效位置/索引,那么为什么IndexOutofBoundException?我的假设是,索引处的null应该替换为“Hello”@JonSkeet:他指的是
java.util.ArrayList
@thinkStiple:不,就列表而言,它不是一个有效的位置。它是一个有效的数组位置,但它大于列表的大小(如
size()
方法所报告的),在该点为0,因为没有添加任何值。你必须区分列表的容量和逻辑大小。索引是5,我认为它比大小(7)小,不是吗?@ThinkStiple:不,大小是0。容量是7。@JonSkeet:知道了。我的头脑真是一团糟。谢谢。+1表示“它是”和“它的”