java提高篇——ArrayList
1. ArrayList概述
ArrayList是实现List接口的动态数组,所谓动态就是它的大小是可变的。实现了所有可选列表操作,并允许包括 null 在内的所有元素。
2. ArrayList源码分析
底层是由数组实现的;
ArrayList list = new ArrayList(); 创建一个对象
默认会创建一个容量为10的数组,注意这个是在调用ArrayList的add方法是创建的
add方法:
add(E e):将指定的元素添加到此列表的尾部。
ensureCapacity()方法是对ArrayList集合进行扩容操作,elementData(size++) = e,将列表末尾元素指向e。
add(int index, E element):将指定的元素插入此列表中的指定位置。
注意这里的System.arraycopy方法,会将从index向后复制移动,十分耗时,所以如果指定的数据集合需要进行大量插入(中间插入)操作,推荐使用LinkedList。
addAll(Collection<? extends E> c):按照指定 collection 的迭代器所返回的元素顺序,将该 collection 中的所有元素添加到此列表的尾部。
System.arraycopy():
addAll(int index, Collection<? extends E> c):从指定的位置开始,将指定 collection 中的所有元素插入到此列表中。
set(int index, E element):用指定的元素替代此列表中指定位置上的元素(这里是覆盖,上面是插入)。
remove方法:
remove(int index):移除此列表中指定位置上的元素。
从上图可以看出数组向前复制移动一位,最后再把perArr[9]设置为null;
remove(Object o):移除此列表中首次出现的指定元素(如果存在)。
这里孙七是不会被删除的!
因为第一个孙七和第二个孙七它们的Hashcode不一样,所以在调用equals方法时,认为它们是两个对象,不会删除,要想删除可以重写equals方法,同时最好也重写HashCode方法。
ArrayList的查找速度很快,根据index索引查找!
3. ArrayList的扩容(基于jdk1.8)
int newCapacity = oldCapacity + (oldCapacity >> 1),>>是移位运算符,相当于int newCapacity = oldCapacity + (oldCapacity/2),但性能会好一些。
这就是数组的扩容,一般是oldCapacity + (oldCapacity >> 1),相当于扩容1.5倍。为什么是1.5倍呢?后面解释
4.总结
ArrayList的增删会引起数组的复制,效率较慢,查找的效率比较高,创建ArrayList最好指定其容量,提高效率