接口
ArrayList实现了List接口,因此可以当作一个List来使用。
此外,ArrayList还实现RandomAccess接口和Serializable,说明ArrayList支持随机访问并且支持Java序列化机制。
实现
ArrayList内部含有的非静态域只有两个,一个用户保存数据的Object数组 elementData,和一个用于表示当前数据数量的size。
为什么不使用elementData的length来表示size呢? 因为elementData的length表示的此ArrayList当前的容量,而不是元素个数。
同时注意到elemantData是生命为transient的,说明这个域的并不是自动序列化的,需要ArrayList自行处理。
从elementData的注释中可以看到,如果当前是一个空的数组,那么当第一个元素被加入时,elementData的大小将会增长到默认大小(10),而不是1.这样做有利于减少数组重新分配的概率,提高运行时效率。
大家都知道,ArraList是支持泛型的,那么为什么要将elementData定义为Object的数组,而不是泛型数组呢? 这是因为泛型参数是不支持new的
部分方法说明
trimToSize()
此方法将elementData的大小调整到刚好能容纳当前的所有元素,以减少内存占用。toArray
无参的形式,会调用Arrays.copyOf将elementData直接拷贝一份作为结果返回,这样调用者就可以直接修改这个返回的数组,而不影响到arrayList。
带一个数组参数的形式,如果传入的数组足以容纳当前的所有元组,则将当前所有元素拷贝到传入的数组中,否则就会新建一个数组并拷贝进去,然后作为结果返回回去。如果传入的数组的大小,超过了当前元素的数量,则会在拷贝进去之后,将拷贝进去的最后一个元素之后的元素置为null,调用着可以根据这个null的位置来判断拷贝了多少个元素进去。ensureCapacity
确保此ArrayList的容量能满足入参要求,如果有必要,会增加ArrayList的容量。contains
通过从前往后顺序遍历元素,对每个元素调用equal的方式,来检查是否包含某个元素。indexOf
通过从前往后顺序遍历元素,对每个元素调用equal的方式,来检查是否包含某个元素,如果包含,返回去下标。lastIndexOf
同indexOf,只是,现在是从后往前开始查找了。grow
这个方法是动态增长数组的核心,首先尝试增加一半的大小,如果增加了一半之后,依然不能满足要求,就直接增加到需要的大小。subList
sublist方法返回给定范围内的子序列,但是要注意,这个方法返回的只是原数组在指定的开始索引和结束索引之间的一个视图,并没有重新开辟一个数组,因此任何对这个sublist的修改,都会反映到原数组上,and
vice versa.
生成了sublist之后,如果直接操作原数组导致结构发生了变化,那么下次操作sublist之后,就会抛出并行修改异常。通过sublist对象来操作则没有问题。