|
|
|
ArrayList 实现了 List 接口,RandomAccess 接口,可以插入空数据以及支持随机访问。它相当于一个动态数组,初始化时是一个空数组,在第一次 add 时设置初始容量为 10,每次扩容都增加到原来的 1.5 倍。简单的 add 就是在 elementData 数组末尾添加一个数据,size++;指定 index 添加数据,就需要拷贝 index 后面的数据后移一位。在删除的时,如果是删除 null,就遍历数组找到第一个 null 值删除,否则就遍历比较 equals 删除指定 index 的数据,其实也就是拷贝 index 后面的数据前移一位。删除数据时,最好使用迭代器来做,避免 CurrentModifyException,它并不只是在并发时才会抛出的,单线程也可能抛出,其实内部是比较 expectedModCount 和 modCount 是否相等来判断的。ArrayList 的性能损耗就来源于数组拷贝,在适当情况下,可以初始化时指定容量大小,避免不必要的扩容操作。其实呢,ArrayList 还有一个缺点,就是不能自动缩容,但是我们可以手动调用 trimToSize 来缩容至当前 size 大小。 |
|
|
|
ArrayList 实现了 List 接口,RandomAccess 接口,可以插入空数据以及支持随机访问。它相当于一个动态数组,初始化时是一个空数组,在第一次 add 时设置初始容量为 10,每次扩容都增加到原来的 1.5 倍。简单的 add 就是在 elementData 数组末尾添加一个数据,size++;指定 index 添加数据,就需要拷贝 index 后面的数据后移一位。在删除的时,如果是删除 null,就遍历数组找到第一个 null 值删除,否则就遍历比较 equals 删除指定 index 的数据,其实也就是拷贝 index 后面的数据前移一位。删除数据时,最好使用迭代器来做,避免 ConcurrentModificationException,它并不只是在并发时才会抛出的,单线程也可能抛出,其实内部是比较 expectedModCount 和 modCount 是否相等来判断的。ArrayList 的性能损耗就来源于数组拷贝,在适当情况下,可以初始化时指定容量大小,避免不必要的扩容操作。其实呢,ArrayList 还有一个缺点,就是不能自动缩容,但是我们可以手动调用 trimToSize 来缩容至当前 size 大小。 |