美文网首页js css html
ArrayList源码解析

ArrayList源码解析

作者: 天还下着毛毛雨 | 来源:发表于2022-09-17 20:29 被阅读0次

    数据结构:数组

    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<? extends E> 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<? extends E> 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<E> {
            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源码解析

        本文链接:https://www.haomeiwen.com/subject/emueortx.html