arraylist元素是有序的,可重复。线程不安全的。底层维护一个 object 数组。
jdk1.7:arraylist像饿汉式,默认初始长度直接创建一个容量为 10 的数组。
jdk1.8:arraylist像懒汉式,默认一开始创建一个长度为 0 的数组,当添加第一个元素时再创建一个始容量为10的数组。
默认情况扩容都为原来数组的 1.5 倍。
继承关系:
扩容原理:
①随机访问
由于实现了 randomaccess 接口,它支持通过索引值去随机访问元素。
②增强foreach,底层还是使用的迭代器
这种语法可以看成是 jdk 的一种语法糖,通过反编译 class 文件,可以看到生成的 java 文件,还是通过调用 iterator 迭代器来遍历的。
③迭代器 iterator
④迭代器 listiterator
源码示例:
继承了abstractlist:abstractlist提供list接口的骨干实现,以最大限度地减少"随机访问"数据存储(如arraylist)实现llist所需的工作。
实现了 list 接口:定义了实现该接口的类都必须要实现的一组方法,实现了所有可选列表操作。
实现了 randmoaccess 接口:表明arraylist支持快速(通常是固定时间)随机访问。此接口的主要目的是允许一般的算法更改其行为,从而在将其应用到随机或连续访问列表时能提供良好的性能。比如在工具类 collections 中,应用二分查找方法时判断是否实现了 randomaccess 接口:
实现了 cloneable 接口:一个标记接口,接口内无任何方法体和常量的声明。需要复写object.clone()函数,表示它可以被克隆。
实现了 serializable 接口:一个标记接口,标识该类可序列化。
源码示例:读一下源码中的英文注释。
源码示例:三个重载(重要)
arraylist list = new arraylist(); // 集合长度初始化是0,而不是 10,jdk7才是10。
arraylist list = new arraylist(7); // 指定大小时,初始多大就是多大。
传入一个集合。
源码示例:扩容原理
源码示例:真正扩容的方法
说明:
modcount给arraylist的迭代器使用的,在并发修改时,提供快速失败行为,保证modcount在迭代期间不变,否则抛出concurrentmodificationexception异常。
arraylist 的扩容,核心方法就是调用 arrays.copyof 方法,创建一个更大的数组,然后将原数组元素拷贝过去。
总结:
①当通过 arraylist() 构造一个空集合,初始长度是为0的,第1次添加元素,会创建一个长度为10的数组,并将该元素赋值到数组的第一个位置。
②第2次添加元素,集合不为空,由于集合大小size + 1 < 数组的长度 10,所以直接添加元素到数组的第二个位置,不用扩容。
③第 11 次添加元素,此时 size+1 = 11 > 数组长度10。这时候创建一个长度为10+10*0.5 = 15 的数组(扩容1.5倍),然后将原数组元素引用拷贝到新数组。并将第 11 次添加的元素赋值到新数组下标为10的位置。
④第 integer.max_value - 8 = 2147483639,然后 2147483639%1.5=1431655759(这个数是要进行扩容)次添加元素,为了防止溢出,此时会直接创建一个 1431655759 + 1 大小的数组,这样一直,每次添加一个元素,都只扩大一个范围。
⑤第 integer.max_value - 7 次添加元素时,创建一个大小为 integer.max_value 的数组,在进行元素添加。
⑥第 integer.max_value + 1 次添加元素时,抛出 outofmemoryerror 异常。
源码示例:将指定索引index处的元素修改。
源码示例:很简单,略
indexof(object o):返回集合中第一次出现该元素的下标,没有则返回 -1。
lastindexof(object o):返回集合中最后一次出现该元素的下标。没有则返回 -1。
返回从 [fromindex, toindex) 的一个子串。但是注意,这里只是原集合的一个视图。
想要独立出来一个集合,解决办法如下:
该方法用于回收多余的内存。可以在确定集合不在添加多余的元素之后,调用 trimtosize() 方法会将数组大小调整为集合元素的大小。
注意:该方法会花时间来复制数组元素,所以应该在确定不会添加元素之后在调用。
迭代器
注意:在进行 next() 方法调用的时候,会进行 checkforcomodification() 调用,该方法表示迭代器进行元素迭代时,如果同时进行增加和删除操作,会抛出 concurrentmodificationexception 异常。比如:
注意:迭代器只能向后遍历,不能向前遍历,能够删除元素,但是不能新增元素。
这是 list 集合特有的迭代器。可以一边遍历,一边新增或删除。
相比于 iterator 迭代器, listiterator 多出了能向前迭代,以及新增元素的功能。
listiterator
在arraylist类中,对上述接口的实现。
作者:craftsman-l