一路至此,风景过半。
ArrayList与Vector虽然名字各异,源码实现基本相同,除了Vector增加了线程安全。所以作者建议我们在不需要线程安全的情况下尽量使用ArrayList。下面看看在ArrayList源码中遇到什么有趣的事情。
DEFAULTCAPACITY_EMPTY_ELEMENTDATA与EMPTY_ELEMENTDATA
|
|
区别:DEFAULTCAPACITY_EMPTY_ELEMENTDATA用于无参初始化;EMPTY_ELEMENTDATA用于指定容量为0时的初始化。
trimToSize()
|
|
去除扩容后未存放元素的预留空间,以size为基准。
ensureCapacity() –> ensureExplicitCapacity() –> grow() –> hugeCapacity()
|
|
预设容量(提前扩容),可提高初始化效率。扩容后比扩容前多了“oldCapacity >> 1”(即多了原来的50%)。同时注意溢出情况处理。(overflow-conscious code)。即“a-b<0”而不是”a<b”:
|
|
toArray()
|
|
当传入数组长度大于ArrayList的size时,将a[size]置空作为调用者判断标志。根据这段代码写了个demo帮助理解:(扩展知识见②)
|
|
add()
|
|
新增、删除都用到了System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length);下面举例加深理解。
|
|
即将arr下标从0开始的2个元素拷贝到arr下标从2开始的位置。
retainAll()
|
|
a.retainAll(c)可以看成取a与c交集,a非c子集时,返回true。a中只留在c中存在的元素,其余删除。否则,返回false。
“elementData[w++] = elementData[r];”w永远小于等于r,因此可以将找到的相等元素大胆的放在elementData[w++]中(elementData[w++]是先放后加)。
iterator()
|
|
Iterator()所指类似数据库的游标,不了解的同学可参看以下解释:
当使用语句Iterator it=List.Iterator()时,迭代器it指向的位置是Iterator1指向的位置,当执行语句it.next()之后,迭代器指向的位置后移到Iterator2指向的位置。[1]
由源码可见ArrayList的迭代器基于Itr子类实现。该类实现了Iterator接口,并重写了它的全部方法(4种)。同时增加了checkForComodification()考虑并发问题。
listIterator()
|
|
listIterator有2中构造方法,即它多了指定游标的功能。它实现了ListIterator
说点什么
private class SubList extends AbstractList
此外,源码中出现了大量泛型(如T、E…)。希望顺便巩固泛型知识。
ArrayList允许为null;非线程安全;有序。
更多有意思的内容,欢迎访问笔者小站: rebey.cn
知识点
1.ArrayList c.toArray might (incorrectly) not return Object[] (see 6260652);2016.09.23;
2.为什么 Java ArrayList.toArray(T[]) 方法的参数类型是 T 而不是 E ?;2016.04.07;
[1]JAVA中ListIterator和Iterator详解与辨析;2014.11.27;