ArrayList源码解析

数据结构:数组

1、 重要成员变量:

size : 已使用的长度

elementData.length : 数组的长度 也就是容量

modCount : 容器被修改的次数, 用于 迭代器遍历的过程中 校验容器是否被修改: 代器初始的时候会赋予它调用这个迭代器的对象的mCount,如何在迭代器遍历的过程中,一旦发现这个对象的mcount和迭代器中存储的mcount不一样那就抛异常

1.操作

1.1操作

System.arraycopy

System.arraycopy(int[] arr, int star,int[] arr2, int start2, length);


第一个参数是要被复制的数组
第二个参数是被复制的数字开始复制的下标
第三个参数是目标数组,也就是要把数据放进来的数组
第四个参数是从目标数据第几个下标开始放入数据
第五个参数表示从被复制的数组中拿几个数值放到目标数组中
比如:
数组1:int[] arr = { 1, 2, 3, 4, 5 };
数组2:int[] arr2 = { 5, 6,7, 8, 9 };
运行:System.arraycopy(arr, 1, arr2, 0, 3);
得到:
int[] arr2 = { 2, 3, 4, 8, 9 };

1.1.1 增加

    添加一个元素
    public boolean add(E e) {
        //判断容量,如果+1之后超出原有大小,就进行扩容
        ensureCapacityInternal(size + 1);
        //数组最末尾下标+1的位置指向添加的元素
        elementData[size++] = e;
        return true;
    }
    指定下标添加元素
    public void add(int index, E element) {
        rangeCheckForAdd(index);
        //判断容量,容量不足进行扩容
        ensureCapacityInternal(size + 1);  
        //讲原来位置在index之后的数据全部对应的移到index+1的位置上
        System.arraycopy(elementData, index,
        elementData, index + 1,
                         size - index);
        //index指向新插入的数据
        elementData[index] = element;
        //已用长度+1
        size++;
    }
    //添加一个集合到arrayList中
    public boolean addAll(Collection c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);
        将集合转为数组后,整个复制到arraylist的末尾
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }
    //添加一个集合到arraylist的指定位置上
    public boolean addAll(int index, Collection c) {
        rangeCheckForAdd(index);
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount
        int numMoved = size - index;
        if (numMoved > 0)
            //相当于index之后的数据放到index+要增加集合的长度之后的位置上,将index到index+要增加集合的长度的位置空出来
            System.arraycopy(elementData, index, elementData, index + numNew,
                             numMoved);
        //将整个要增加的集合复制到空出来的位置上
        System.arraycopy(a, 0, elementData, index, numNew);
        size += numNew;
        return numNew != 0;
    }

1.1.1.2扩容

    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        // 旧容量 + 旧容量右移1位,就是除以2 的 值
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        // 可能初始化arrayList的时候是0,1,此时上一个表达式 计算之后的值 并不会比原值大(精度丢失)
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        // 拓宽数组,把原数组 复制到一个长度更大的数组中
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

1.1.1.2删除

     //删除指定元素
     public E remove(int index) {
        rangeCheck(index);

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

        int numMoved = size - index - 1;
        //将index+1的元素复制到index上
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }
    //删除某元素
    public boolean remove(Object o) {
        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;
    }

1.1.1.3 获取

    //获取某下标元素:根据数组下标获取
    public E get(int index) {
        rangeCheck(index);
        return elementData(index);
    }

1.1.1.3 设置

    public E set(int index, E element) {
        rangeCheck(index);
        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }

1.1.1.3 迭代器

    private class Itr implements Iterator {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        Itr() {}

        public boolean hasNext() {
            //判断游标是否等于列表长度
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;//每次next()都将游标后移一位
            //返回数组中对应游标位置的数据,并将后移前的游标值赋给lastRet
            return (E) elementData[lastRet = i];
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.remove(lastRet);
                //如果中途删除,将当前游标赋给lastRetm让下一次的next获取的数组下标还是当前下标
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

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