ArrayList的介绍和源码解析

ArrayList的介绍

1 ArrayList简介

ArrayList是List 接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。(此类大致上等同于 Vector 类,除了此类是不同步的。),此类是线程不安全的。

2 ArrayList的构造函数

public ArrayList()    //默认构造函数
public ArrayList(int initialCapacity)   //生成一个指定容量的空列表
public ArrayList(Collection c)  //生成一个包含指定元素的列表

3 ArrayList的Api

void        trimToSize    //把列表的容量修剪成列表的实际容量,删除动态增长的多余容量。
void        ensureCapacity(int minCapacity)   //根据传入的值对数组进行扩容,在数量已知的情况下
void        ensureCapacityInternal(int minCapacity)    //私有方法,根据传入的值对数组进行扩容
void        ensureExplicitCapacity(int minCapacity)   //传入数组进行扩容
void        grow(int minCapacity)     //进行扩容
int         hugeCapacity(int minCapacity)   //根据传入的值判断当前大小是否超过数组最大的大MAX_ARRAY_SIZE= Integer.MAX_VALUE - 8
int         size()    //获取列表大小
boolean     isEmpty()  //判断对象是否为空
boolean     contains(Object o)   //判断是否包含某个对象
int         indexOf(Object o)   //根据对象查询第一个索引下标
int         lastIndexOf(Object o)    //根据对象查询最后一个索引下标
Object      clone()   //对象进行复制
Object[]    toArray()  //将列表对象转成Object数组
T[]         toArray(T[] a)    //将列表对象转成某个固定对象的数组
E           elementData(int index)    //通过下标访问对象,内部方法
E           get(int index)    //通过下标访问对象
E           set(int index, E element)    //替换某个下标位置上的对象
boolean     add(E e)      //添加对象
void        add(int index, E element)   //在某个位置上添加对象,如果当前位置有相应的对象,则位置往右递增
E           remove(int index)     //删除某个对象通过下标
boolean     remove(Object o)   //通过对象查找删除某个对象 通过equals判断
void        fastRemove(int index)  //通过对象删除时的删除方法
void        clear()       //数据清空
boolean     addAll(Collection c)  //添加一个Collection队列到当前列表中
boolean     addAll(int index, Collection c)  //从某个位置开始添加一个Collection队列到当前列中
void        removeRange(int fromIndex, int toIndex)   //删除某个区间的数据
void        rangeCheck(int index)   //验证当前下标是否在实际数据范围内
void        rangeCheckForAdd(int index)   //添加数据到某个下标时 判断是否超过范围
String      outOfBoundsMsg(int index)  //数组越界显示字段
boolean     removeAll(Collection c)    //删除传入的列表对象
boolean     retainAll(Collection c)      //获取两个元素的交集 并把数据存入前面的列表中 l1.retainAll(l2)
boolean     batchRemove(Collection c, boolean complement)   私有方法  //retainAll调用的内部方法    
void        writeObject(java.io.ObjectOutputStream s)    //
void        readObject(java.io.ObjectInputStream s)   //和WriteObject重写序列化方法
ListIterator listIterator(int index)   //返回一个ListIterator从下标位置开始
ListIterator listIterator()    //返回一个ListIterator接口的实现对象,下标从0开始
Iterator iterator()  //返回Iterator接口具体实现对象
List     subList(int fromIndex, int toIndex)  //返回开始和结束下标中的对象
void        subListRangeCheck(int fromIndex, int toIndex, int size)   //判断取区间对象是是否
void        forEach(Consumer action)   //输出对象
Spliterator spliterator()    //生成一个Spliterator对象,用于遍历和分割队列 一般配合Collection的stream方法使用,1.8新增方法
boolean     removeIf(Predicate filter)   //移除满足条件的所有元素
void        sort(Comparator c)   //列表进行排序

ArrayList的数据结构

ArrayList里面的重要字段说明

elementData:Object类型的数组,存放ArrayList添加进来的元素,是一个动态数组,大小会根据ArrayList的容量的增长而增长。
size:ArrayList中实际数据的大小。
modCount:实现fail-fast机制,不同线程对同一个集合进行操作是的错误机制

ArrayList的重要方法源码解析

//数据的添加
public boolean add(E e) {   //添加一个数据元素
        ensureCapacityInternal(size + 1);  // Increments modCount!!    //确定ArrayList的大小
        elementData[size++] = e;   //添加e元素到ArrayList中 并ArrayList大小加1
        return true;
    }

public void add(int index, E element) {  //添加一个元素到指定位置
        rangeCheckForAdd(index);   //判断当前位置是否越界(超出当前ArrayList大小和小于0)

        ensureCapacityInternal(size + 1);  // Increments modCount!!   //确定ArrayList的大小
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);   //把新元素存放位置后面的元素往后移动一位
        elementData[index] = element;  //把新元素放到指定位置
        size++;  //ArrayList大小加1
    }

public boolean addAll(Collection c) {  //往ArrayList中添加一个Collection集合
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount  //把传入集合转为数组对象,通过长度确定ArrayList大小
        System.arraycopy(a, 0, elementData, size, numNew);  //把转为数组对象的Collection集合添加到ArrayList中
        size += numNew;
        return numNew != 0;
    }

public boolean addAll(int index, Collection c) {  //添加一个Collection集合到ArrayList中的指定位置
        rangeCheckForAdd(index);

        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount  把传入集合转为数组对象,通过长度确定ArrayList大小

        int numMoved = size - index;
        if (numMoved > 0)
            System.arraycopy(elementData, index, elementData, index + numNew,
                             numMoved);    //计算指定位置插入数据是原数据往后移动位置,并移动

        System.arraycopy(a, 0, elementData, index, numNew);  //把转为数组对象的Collection集合添加到ArrayList中
        size += numNew; //确定size
        return numNew != 0;
    }

private void ensureCapacityInternal(int minCapacity) {    //确定ArrayList的大小
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {   //判断是否为默认创建的空元素
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);  //大小为默认大小和传进来大小去最大值
        }

        ensureExplicitCapacity(minCapacity);  
    }

private void ensureExplicitCapacity(int minCapacity) {  //判断并确定ArrayList大小
        modCount++;   //证明进行了ArrayList的数据添加操作

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)   //如果传进来的大小大于现在数组大小,就对数组进行自增操作
            grow(minCapacity);
    }

private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);  //自增的大小默认为原大小的1.5倍
        if (newCapacity - minCapacity < 0)   //如果自增大小小于添加数据后的带下,新的自增大小更改为传入数据大小
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)   //如果自增大小大于ArrayList中自定义最大大小,就把大小设置为int值得最大大小范围
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);  //数组进行自增
    }

private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }
//ArrayList数据删除
public boolean remove(Object o) {   //通过对象删除对象 通过循环ArrayList中的元素查找到需要删除的对象进行删除
        if (o == null) {  
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }

private void fastRemove(int index) {  //快速删除对象 不需要对位置进行判断
        modCount++;
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work
    }

protected void removeRange(int fromIndex, int toIndex) {  //删除一个范围内的数据
        modCount++;
        int numMoved = size - toIndex;  //通过删除最后的下标往前移动 然后把取消的数据设为null值
        System.arraycopy(elementData, toIndex, elementData, fromIndex,
                         numMoved);

        // clear to let GC do its work
        int newSize = size - (toIndex-fromIndex);
        for (int i = newSize; i < size; i++) {
            elementData[i] = null;
        }
        size = newSize;
    }

public E remove(int index) {  //通过下标删除对象
        rangeCheck(index);  //判断指定位置是否在数据大小之中

        modCount++;
        E oldValue = elementData(index);  

        int numMoved = size - index - 1;  //是否需要移动 最后一个元素不需要移动其他位置的元素
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work  //最后一个元素设为null值

        return oldValue;
    }

public boolean removeAll(Collection c) {  //删除ArrayList中存在的输入的集合的元素 
        Objects.requireNonNull(c);  //判断是否为空
        return batchRemove(c, false);
    }

private boolean batchRemove(Collection c, boolean complement) {
        final Object[] elementData = this.elementData;
        int r = 0, w = 0;
        boolean modified = false;  
        try {
            for (; r < size; r++)
                if (c.contains(elementData[r]) == complement)   //complement:true 返回相同的元素 false 返回不同元素
                    elementData[w++] = elementData[r];
        } finally {
            if (r != size) {  //如果不等于证明前面报了异常,把后面的部分补全
                System.arraycopy(elementData, r,
                                 elementData, w,
                                 size - r);
                w += size - r;
            }
            if (w != size) {    //如果w!=size说明进行了删除操作,故需将删除的值赋为null
                for (int i = w; i < size; i++)
                    elementData[i] = null;
                modCount += size - w;
                size = w;
                modified = true;
            }
        }
        return modified;
    }
public E get(int index) {  //通过下标返回数据 先判断下标是否正确
        rangeCheck(index);

        return elementData(index);
    }

ArrayList的遍历方式

1、通过迭代器的方式去实现,既Iterator的方式

Iterator iterator = list.iterator;
while(iterator.hasNext()){
    String value = iterator.next();
}

2、通过索引随机访问,ArrayList默认实现了RandomAccess

  for(int i = 0;i

3、通过ForEach循环遍历

 for(String str:list){
    String value = str;
}

通过对比三种方式中随机访问的效率,迭代器的方式效率最低

你可能感兴趣的:(ArrayList的介绍和源码解析)