ArrayList简介
- ArrayList内部是以动态数组存放数据的,所谓动态数组,不是数组本身可以改变长度,而是保留原有数组引用的情况下创建一个新的数组,使用体验就像是可自动扩容的数组。
- ArrayList内部是数组,支持数组的所有特性,通过索引支持随机访问,所以访问效率高,但是插入和删除效率低下。
- ArrayList实现了AbstractList抽象类、List接口、所以其更具有了AbstractList和List的功能,AbstractList内部已经实现了获取Iterator和ListIterator的方法,所以ArrayList只需关心对数组操作的方法即List接口的实现。
- ArrayList实现了RandomAccess接口、此接口只有声明、没有方法体、表示ArrayList支持随机访问。
- ArrayList实现了Cloneable接口、此接口只有声明、没有方法体、表示ArrayList支持克隆。
- ArrayList实现了Serializable接口、此接口只有声明、没有方法体、表示ArrayList支持序列化、即可以将ArrayList以流的形式通过ObjectInputStream/ObjectOutputStream来写/读。
ArrayList的扩容
- 初始容量为10:使用无参构造的创建ArrayList的时候默认容量为10。
- 扩容规则:每次add元素(单个或者一组)的时候,都要先检查容量是否够用。如果发现容量不够,就设置新容量为原有容量1.5倍+1,如果新容量还不够用,就直接把新容量设置为能盛放当前元素量的值。然后就是使用Arrays.copyOf()方法把原数据copy到新数组中去。由此可见,使用ArrayList尽量明确使用上限,自动扩容虽好,但是效率不高。
- 为什么是1.5倍:跟源代码中的算法有关“oldCapacity + (oldCapacity >> 1);”
- Arrays.copyOf():最终使用的是操作系统的api进行数组复制,效率比我们手写代码要高。
- 扩容限制:扩容并非是无限制的,有内存限制,虚拟机限制。
手写ArrayList帮助理解
public class MyArrayList<T> implements Iterable<T> {
private T[] theItems;
private int theSize;
private static final int DEAULT_CAPACITY=10;
public MyArrayList(){
theSize=0;
ensureCapacity(DEAULT_CAPACITY);
}
public void add(T data){
if(size()==theItems.length){
ensureCapacity(size()*2+1);
}
theItems[size()]=data;
theSize++;
}
public void add(int index,T data){
if(size()==theItems.length){
ensureCapacity(size()*2+1);
}
for(int i=theSize;i>index;i--){
theItems[i]=theItems[i-1];
}
theItems[index]=data;
theSize++;
}
public T get(int index){
if(index<0|index>=size()){
throw new IndexOutOfBoundsException("index error");
}
return theItems[index];
}
public T remove(int index){
T removeData=get(index);
for(int i=index;i<size()-1;i++){
theItems[i]=theItems[i+1];
}
theSize--;
return removeData;
}
public int size(){
return theSize;
}
private void ensureCapacity(int newCapacity){
if(theSize>newCapacity){
return;
}
T[] old=theItems;
theItems= (T[]) new Object[newCapacity];
for(int i=0;i<size();i++){
theItems[i]=old[i];
}
}
@Override
public Iterator<T> iterator() {
return null;
}
@Override
public void forEach(Consumer<? super T> action) {
}
@Override
public Spliterator<T> spliterator() {
return null;
}
}
参考文章:
Java容器之ArrayList
网友评论