ArrayList 的 add(index,object) 方法抛出 IndexOutOfBoundException
ArrayList's add(index,object) method throw IndexOutOfBoundException
关于使用下面提到的代码片段创建 arrayList:
List arrayList = new ArrayList(16);
ArrayList 的内部实现创建一个大小为 16 的数组 elementData
并在每个位置分配 null
。在做类似 arrayList.add(2,"HelloWorld")
的事情时给出 IndexOutOfBoundException
作为添加元素的索引(即 2)大于 size
arrayList
的属性。
从javaDocs中可以清楚地看出,arrayList的size
属性在初始化arrayList
时初始化为0,每次递增1 arrayList
添加了一个新元素
谁能解释一下,为什么 ArrayList
dataStructure 最初是这样设计的。即使内部数据结构 elementData
在创建 arrayList 时被初始化为 16 个空值,它仍然不允许在 indeces > size 处添加值; (假设在这种情况下索引 <16)。实现 add(index,object) 的想法是什么
由 arrayList 的大小属性控制的功能?
拥有一个大小大于 List.size() 的内部数组的目的是避免不必要地重新分配数组。如果内部数组总是和 List 有相同的大小,那么每次添加新元素时,内部数组都必须重新分配,从而导致性能下降。
您不能在特定索引处添加对象,直到它包含 null。您只需要使用 add 方法添加对象,然后就可以更新索引上的值。
例如
ArrayList<Integer> arrlist = new ArrayList<Integer>(5);
// use add() method to add elements in the list
arrlist.add(15);
arrlist.add(22);
arrlist.add(30);
arrlist.add(40);
// adding element 25 at third position
arrlist.add(2,25);
您很少需要指定 ArrayList
的 容量 ,只有当您知道 ArrayList
将容纳多少元素时,它才能提高性能.
ArrayList
只是一个可以自动增大或缩小的 List
。使用 List
,你 永远不会 需要在 n
的地方添加一个元素,如果列表是空的,你只需 link 它到前一个节点(当然除非它是头) - 这就是 ArrayList
的想法,除了它可以 grown/shrink 自动。
其实ArrayList的默认构造函数构造的是一个初始容量为10的列表
public ArrayList() {
this(10);
}
但是为什么我们需要这样的分配呢?正如您所理解的,如果您预先指定 ArrayList 的大小,则可以为列表提供高效。否则,当元素个数超过ArrayList的初始容量后,对每个元素重新进行重新分配操作
public void add(int index, E element)
Throws:
IndexOutOfBoundsException -
if the index is out of range
(index < 0 || index > size())
如您所见,如果 (index > size()),它会抛出 IndexOutOfBoundsException。
由于 ArrayList 的 "public int size()" returns 元素不等于 null,因此您的大小等于 0(不是您在示例中所说的 16)。换句话说,如果也计算空值,则使用默认构造函数创建的每个 ArrayList 的大小将为 10.
因此,"arrayList.add(2, "HelloWorld")" 抛出 IndexOutOfBoundsException,因为 index = 2 但 size() = 0。
编辑:
我想当你提出你的论点时,你使用这个作为基础:
String[] arr = new String[5];
arr[3] = "hello";
System.out.println(arr[3]);
然后,你想为什么你可以直接给数组元素赋值,为什么你不能用ArrayList的add(int index, E element)方法来做同样的事情。实际上,这是真的,但没有条件将 ArrayList 实现为 Array 的完整对应物。换句话说,此方法以该规则为条件,因为它是 ArrayList 的本质。众所周知,当你创建一个数组时,你在方括号中指定它的大小。以 int 作为参数的 ArrayList 的构造函数不做同样的事情。它只执行虚构的分配。是的,它可以通过此分配指定其初始大小,或者在调用 add(int index, E element) 后,大小可以增加一。但是,实现 ArrayList 是为了提供一种类似数组的结构,该结构在索引号方面具有连续性,但没有固定大小。因此,有一些其他更高级别的抽象示例可以完成此任务。举个例子,LinkedHashMap结构。
参见 ArrayList
的 java 文档 add(int index,
E元素)方法。在这里您可以找到 ArrayIndexOutOfBound
异常发生在 if the index is out of range (index < 0 || index > size())
时。
您声明了一个初始容量为 16 的 ArrayList
。这并不意味着 ArrayList
的 16 个索引位置中的每一个都包含元素。它只提到初始容量,必要时它会动态增加它的大小。
从ArrayList
class-
查看构造函数的源代码
/**
* Constructs an empty list with the specified initial capacity.
*
* @param initialCapacity the initial capacity of the list
* @exception IllegalArgumentException if the specified initial capacity
* is negative
*/
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
}
在这里我们找不到任何告诉我们的信息 - ArrayList
将以空值启动。
更新: 根据您的评论,我做了一些实验,因为我不确定 reference/non-primitive 类型的数组是否会初始化为 null。请参阅下面的代码。 运行 通过在每次执行时取消注释每一行的代码 -
import java.util.List;
import java.util.ArrayList;
public class ArrayListTest{
public static void main(String[] args){
List<String> list1 = new ArrayList<String>(); //default with initial capacity 10
List<String> list2 = new ArrayList<String>(5);
List<String> list3 = new ArrayList<String>(5);
list2.add(null);
list2.add(null);
list2.add(null);
list3.add("zero");
list3.add("one");
list3.add("two");
//System.out.println(list1.get(4)); //IndexOutOfBoundException
//System.out.println(list2.get(0)); //null
//System.out.println(list2.get(2)); //null;
//System.out.println(list2.get(3)); //IndexOutOfBoundException
//System.out.println(list3.get(0)); //zero
//System.out.println(list3.get(2)); //two;
//System.out.println(list3.get(3)); //IndexOutOfBoundException
//list3.add(4, "four"); //IndexOutOfBoundException
}
}
在这里你可以看到 list2.get(0)
和 list2.get(2)
给你 null。因为我们将 null 放在这些索引处。但是 list2.get(3)
没有给出 null
因为我们没有把 null
放在索引 3 处。所以 reference/non-primitive 类型的数组似乎不会用 [=22= 初始化]. list2.get(3)
给出 IndexOutOfBoundException
。
您发现 list3.
的情况相同,但我没有在此列表中放置任何 null
。即使我们试图在 list3
的索引 4 处添加一些值,它也会给出 IndexOutOfBoundException
。由于索引 4 不适用于 list3
。但是您可以在 list2
的索引 2 处添加一些值。因为在此列表的索引 2 处,我手动插入了 null
。
长话短说(我认为)- new ArrayList<SomeType>(givenSize)
不会用 givenSize
初始化数组,所有元素设置为 null
。
希望对您有所帮助。
谢谢。
关于使用下面提到的代码片段创建 arrayList:
List arrayList = new ArrayList(16);
ArrayList 的内部实现创建一个大小为 16 的数组 elementData
并在每个位置分配 null
。在做类似 arrayList.add(2,"HelloWorld")
的事情时给出 IndexOutOfBoundException
作为添加元素的索引(即 2)大于 size
arrayList
的属性。
从javaDocs中可以清楚地看出,arrayList的size
属性在初始化arrayList
时初始化为0,每次递增1 arrayList
谁能解释一下,为什么 ArrayList
dataStructure 最初是这样设计的。即使内部数据结构 elementData
在创建 arrayList 时被初始化为 16 个空值,它仍然不允许在 indeces > size 处添加值; (假设在这种情况下索引 <16)。实现 add(index,object) 的想法是什么
由 arrayList 的大小属性控制的功能?
拥有一个大小大于 List.size() 的内部数组的目的是避免不必要地重新分配数组。如果内部数组总是和 List 有相同的大小,那么每次添加新元素时,内部数组都必须重新分配,从而导致性能下降。
您不能在特定索引处添加对象,直到它包含 null。您只需要使用 add 方法添加对象,然后就可以更新索引上的值。
例如
ArrayList<Integer> arrlist = new ArrayList<Integer>(5);
// use add() method to add elements in the list
arrlist.add(15);
arrlist.add(22);
arrlist.add(30);
arrlist.add(40);
// adding element 25 at third position
arrlist.add(2,25);
您很少需要指定 ArrayList
的 容量 ,只有当您知道 ArrayList
将容纳多少元素时,它才能提高性能.
ArrayList
只是一个可以自动增大或缩小的 List
。使用 List
,你 永远不会 需要在 n
的地方添加一个元素,如果列表是空的,你只需 link 它到前一个节点(当然除非它是头) - 这就是 ArrayList
的想法,除了它可以 grown/shrink 自动。
其实ArrayList的默认构造函数构造的是一个初始容量为10的列表
public ArrayList() {
this(10);
}
但是为什么我们需要这样的分配呢?正如您所理解的,如果您预先指定 ArrayList 的大小,则可以为列表提供高效。否则,当元素个数超过ArrayList的初始容量后,对每个元素重新进行重新分配操作
public void add(int index, E element)
Throws:
IndexOutOfBoundsException - if the index is out of range (index < 0 || index > size())
如您所见,如果 (index > size()),它会抛出 IndexOutOfBoundsException。 由于 ArrayList 的 "public int size()" returns 元素不等于 null,因此您的大小等于 0(不是您在示例中所说的 16)。换句话说,如果也计算空值,则使用默认构造函数创建的每个 ArrayList 的大小将为 10.
因此,"arrayList.add(2, "HelloWorld")" 抛出 IndexOutOfBoundsException,因为 index = 2 但 size() = 0。
编辑:
我想当你提出你的论点时,你使用这个作为基础:
String[] arr = new String[5];
arr[3] = "hello";
System.out.println(arr[3]);
然后,你想为什么你可以直接给数组元素赋值,为什么你不能用ArrayList的add(int index, E element)方法来做同样的事情。实际上,这是真的,但没有条件将 ArrayList 实现为 Array 的完整对应物。换句话说,此方法以该规则为条件,因为它是 ArrayList 的本质。众所周知,当你创建一个数组时,你在方括号中指定它的大小。以 int 作为参数的 ArrayList 的构造函数不做同样的事情。它只执行虚构的分配。是的,它可以通过此分配指定其初始大小,或者在调用 add(int index, E element) 后,大小可以增加一。但是,实现 ArrayList 是为了提供一种类似数组的结构,该结构在索引号方面具有连续性,但没有固定大小。因此,有一些其他更高级别的抽象示例可以完成此任务。举个例子,LinkedHashMap结构。
参见 ArrayList
的 java 文档 add(int index,
E元素)方法。在这里您可以找到 ArrayIndexOutOfBound
异常发生在 if the index is out of range (index < 0 || index > size())
时。
您声明了一个初始容量为 16 的 ArrayList
。这并不意味着 ArrayList
的 16 个索引位置中的每一个都包含元素。它只提到初始容量,必要时它会动态增加它的大小。
从ArrayList
class-
/**
* Constructs an empty list with the specified initial capacity.
*
* @param initialCapacity the initial capacity of the list
* @exception IllegalArgumentException if the specified initial capacity
* is negative
*/
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
}
在这里我们找不到任何告诉我们的信息 - ArrayList
将以空值启动。
更新: 根据您的评论,我做了一些实验,因为我不确定 reference/non-primitive 类型的数组是否会初始化为 null。请参阅下面的代码。 运行 通过在每次执行时取消注释每一行的代码 -
import java.util.List;
import java.util.ArrayList;
public class ArrayListTest{
public static void main(String[] args){
List<String> list1 = new ArrayList<String>(); //default with initial capacity 10
List<String> list2 = new ArrayList<String>(5);
List<String> list3 = new ArrayList<String>(5);
list2.add(null);
list2.add(null);
list2.add(null);
list3.add("zero");
list3.add("one");
list3.add("two");
//System.out.println(list1.get(4)); //IndexOutOfBoundException
//System.out.println(list2.get(0)); //null
//System.out.println(list2.get(2)); //null;
//System.out.println(list2.get(3)); //IndexOutOfBoundException
//System.out.println(list3.get(0)); //zero
//System.out.println(list3.get(2)); //two;
//System.out.println(list3.get(3)); //IndexOutOfBoundException
//list3.add(4, "four"); //IndexOutOfBoundException
}
}
在这里你可以看到 list2.get(0)
和 list2.get(2)
给你 null。因为我们将 null 放在这些索引处。但是 list2.get(3)
没有给出 null
因为我们没有把 null
放在索引 3 处。所以 reference/non-primitive 类型的数组似乎不会用 [=22= 初始化]. list2.get(3)
给出 IndexOutOfBoundException
。
您发现 list3.
的情况相同,但我没有在此列表中放置任何 null
。即使我们试图在 list3
的索引 4 处添加一些值,它也会给出 IndexOutOfBoundException
。由于索引 4 不适用于 list3
。但是您可以在 list2
的索引 2 处添加一些值。因为在此列表的索引 2 处,我手动插入了 null
。
长话短说(我认为)- new ArrayList<SomeType>(givenSize)
不会用 givenSize
初始化数组,所有元素设置为 null
。
希望对您有所帮助。
谢谢。