• ArrayList源码解析


    UML

    ArrayList UML

    主要代码

    ArrayList实现了List、RandomAccess、Cloneable、Serializable,继承了AbstractList。
    为什么继承了AbstractList还要实现List接口?
    AbstractList中已经实现了List接口,这里其实是没有必要再实现List接口的,这个获取是为了体现面向接口编程。
    RandomAccess接口:该接口在jdk中是一个空实现,是一个标记接口。文档指明实现了RandomAccess说明List支持随机访问。这个接口的主要目的是允许普通算法对随机方法或者连续访问List时,改变其行为,以获得较好的性能。

    默认初始容量为10,每次扩容1.5倍,底部存储使用数组。

    public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
        // 默认容量10
        private static final int DAFAULT_CAPACITY = 10;
        // 当传入的容量大小为0时,使用该空的常量数组对象来初始化底层数组elementData
        private static final Object[] EMPTY_ELEMENTDATA = {};
        
        // 当未指定容量大小时,使用该空的常量数组对象来初始化底层数组elementData,,这时,当第一次添加元素时,将会默认创建一个容量为10的默认容量数组。
        private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
        
        // 存储ArrayList中的元素,使用transient是为了不序列化这个字段
        transiemt Object[] elementData;
        
        // 集合中元素的个数, 不是底层数组elementData的长度
        private int size; 
        
        // 最大容量,即elementData数组的最大长度,超过该长度将会抛出OutOfMemoryError
        private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
        
        // 结构性修改次数,定义在AbstractList中
        protected transient int modCount = 0;
        
        /**
         * 构造一个指定容量的集合
         * 根据参数大小做为容量来实例化底层的数组对象,当参数等于0时,用空的常量数组对象EMPTY_ * ELEMENTDATA来初始化底层数组elementData
         */
        public ArrayList(int initialCapacity) {
            if(initialCapacity > 0) {
                this.elementData = new Object[intialCapacity];
            }else if(initialCapacity == 0) {
                this.elementData = EMPTY_ELEMENTDATA;
            }else {
                throw new IllegalArgumentException("Illegal Capacityy : " + initialCapacity);;
            }
        } 
        
        /**
         * 构造一个初始容量为10的空集合
         * 这里并没有指定容量,那么我们怎么知道是10呢?答案请看add(E e)
         */
        public ArrayList() {
            this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENT;
        }
        
        /**
         * 将容器Collection转化为数组赋值给底层数组elementData
         */
        public ArrayList(Collection<? extends E> c) {
            // 集合转化为数组
            elelementData = c.toArray();
            if((size = elementData.length) != 0) {
                // 将c.toArray()返回的是不是Object[]类型,如果不是重新拷贝生成Object[]类型
                if(elementData.getClass != Object[].class) {
                    elementData = Arrays.copyOf(lementData, size, Ojbect[].class);
                }
            }else {
                // 如果是空集合,则初始化为空数组EMPTY_ELEMENTDATA
                this.elementData = EMPTY_ELEMENTDATA;
            }
        }
        
        /**
         * 将指定元素e添加到list的末尾,平均时间时间复杂度O(1)
         * 1.计算最小容量minCapacity
         *   如果elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA,最小容量为max(DEFAULT_CAPACITY, minCapacity)
         *   否则为size + 1
         * 2.检查当前elementData容量是否够minCapacity,不够进行扩容
         * 3.将size位置的元素设置e
         */
        public boolean add(E e) {
            // 检查是否需要进行扩容
            ensureCapacityInternal(size + 1);
            // 将size位置设置为e,并将size++;
            elementData[size++] = e;
            return true;
        }
        
        /**
         * 添加元素到指定位置
         * 1.检查是否越界 0 <= index <= size
         * 2.检查是否需要扩容
         * 3.将index之后的元素后移一位
         * 4.设置index位置的元素为elementData
         */ 
        public void add(int index, E element) {
            rangeCheckForAdd(index);
            ensureCapacityInternal(size + 1);
            System.arraycopy(elementData, index, elementData, index + 1, size - index);
            elementData[index] = element;
            size++;
        }
        
        // addAll(Collection<? extends E> c)、addAll(int index, Collection<? extends E> c) 逻辑与add(int index, E element)相似
        
        public boolean addAll(Collection<? extends E> c) {
            Object[] a = c.toArray();
            int numNew = a.length;
            ensureCapacityInternal(size + numNew);
            
            System.arraycopy(a, 0, elementData, size, numNew);
            size += numNew;
            return numNew != 0;
        }
        
        public boolean addAll(int index, Collection<? extends E> c) {
            rangeCheckForAdd(index);
            Object[] a = c.toArray();
            int numNew = a.length;
            ensuerCapacityInternal(size + numNew);
            
            int numMoved = size - index;
            if(numMoved > 0) {
               System.arraycopy(elementData, index, elementData, index + numMoved , numMoved);
            }
            System.arraycopy(a, 0, elementData, index, numNew);
            size += numNew;
            return numNew != 0;
            
        }
        
        /**
         * 设置index位置的元素为element
         */
        public E set(int index, E element) {
            rangeCheck(index);
            
            E oldValue = elementData(index);
            elementData[index] = element;
            return oldValue;
        }
        
        /**
         * 获取指定位置index上的元素
         */
        public E get(int index) {
            // 检查是否越界 0 <= index < this.size
            rangeCheck(index);
            // 返回底层数组index位置的元素
            return elementData[index];
        }
        
        /**
         * 从头开始查找对象o在list中的索引位置
         * 查找分o为null和非null两种情况,没有找到返回-1
         */
        public int indexOf(Object o) {
            if(o == null) {
                for(int i = 0; i < size; i++) {
                    if(elementData[i] == null) {
                        return i;
                    }
                }
            }else {
                for(int i = 0; i < size; i ++) {
                    if(o.equals(elementData[i])) {
                        return i;
                    }
                }
            }
            return -1;
        }
    
        /**
         * 从尾部开始查找对象o所在索引位置
         */
        public int lastIndexOf(Object o) {
            if (o == null) {
                for (int i = size-1; i >= 0; i--)
                    if (elementData[i]==null)
                        return i;
            } else {
                for (int i = size-1; i >= 0; i--)
                    if (o.equals(elementData[i]))
                        return i;
            }
            return -1;
        }
        
        /**
         * 移除index位置的元素
         * 1.检查index是否越界
         * 2.结构性修改次数加1
         * 3.将index后面的元素向前移动一位
         * 4.将最后一位置为空,并返回移除的元素
         */
        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;
            return oldValue;
        }
        
        public boolean remove(Object o) {
            if(o == null) {
                for(int index = 0; index < size; index++) {
                    if(elementData == null) {
                        fastRemove(index);
                        return true;
                    }
                }
            } else {
                for(int index = 0; index < size; index++) {
                    if(o.equals(elementData[index])) {
                        fastRemove(index);
                        return true;
                    }
                }
            }
            
            return false;
        }
        
        /**
         * 移除指定集合c中元素
         */ 
        public boolean removeAll(Collection<?> c) {
            // c不能为null
            Objects.requireNonNull(c);
            return batchRemove(c, false);
        }
        
        /**
         * 对list中的所有元素执行operator.apply()
         */
        public void replaceAll(UnaryOperator<E> oprator) {
            Objects.requireNonNull(operator);
            final int expectedModCount = modCount;
            final int size = this.size;
            for(int i = 0; modCount == expectedCount && i < size; i++) {
                elementData[i] = operator.apply((E)element[i]);
            }
            if(modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
            modCount++;
        }
        
        /**
         * list排序,直接调用Arrays.sort()。只对0,size之间的元素进行排序
         */
        public void sort(Comparator<? super E> c) {
            final int expectedModCount = modCount;
            Array.sort((E[]) elementData, 0, size, c);
            if(modCount != expectedModCount) {
                throw new ConcurrentModification Exception();
            }
            modCount++;
        }
        
        /**
         * elementData使用了transient,所以序列化时不会将elementData序列化,
         * 这里将ArrayList写入到序列化流中
         */
        private void writeObject(ObjectOutputStream s) throws IOException {
            int expectedModCount = modCount;
            s.defaultWriteObject();
            
            s.writeInt(size);
            for(int i = 0; i < size; i++) {
                s.writeObject(elementData[i]);
            }
            if(modCount != elementModCount) {
                throw new ConcurrentModificationException();
            }
        }
        
        /**
         * 从流中反序列化
         */
        private void readObject(ObjectInputStream s) throws IOEception, ClassNotFoundException {
            elementData = EMPTY_ELEMENTDATA;
            s.defaultReadObject();
            s.readInt();
            if(size > 0) {
                int capacity = calculateCapacity(elementData, size);
                Shared.getJavaOISAccess().checkArray(s, Object[].class, capacity);
                ensureCapacityInternal(size);
                
                Object[] a = elementData;
                for(int i = 0; i < size; i++) {
                    a[i] = s.readObject();
                    
                }
                
            }
        }
        
        
        private void fastRemove(index) {
            modCount++;
            int numMoved = size - index - 1;
            if(numMoved > 0) {
                System.arraycopy(elementData, index + 1, elementData, index, numMoved);
            }
            elementData[--size] = null;
        }
        
        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) {
                        // 如果list中该元素不存在与collection中,就放入elementData
                        elementData[w++] = elementData[r];
                    }
                }finally {
                    if(r != size) {
                        System.arraycopy(elementData, r, elementData, w, size - r);
                        w += size - r;
                    }
                    // 如果list中确实有collection中的元素,那么w一定不等于size
                    if(w != size) {
                        // 将其他元素设置为null,这样elementData中就只有不在collection中的元素了,并且多余的索引位置并设置为了null
                        for(int i = w; i < size; i++) {
                            elementData[i] = null;
                        }
                        // 修改次数
                        modCount += size -w;
                        // size等于w
                        size = w;
                        // 移除过元素
                        modified = true;
                    }
                }
                return modified;
            }
        }
    
        
        private void ensureCapacityInternal(int minCapacity) {
            ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
        }
        
        /**
         * 计算最小容量
         * 1,如果elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA,那么取DEFAULT_CAPACITY和minCapacity中的较大者
         * 2.取minCapacity
         */
        private static int calculateCapacity(Object[] elementData, int minCapacity) {
            if(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
                return Math.max(DEFAULT_CAPCITY, minCapacity);
            }
            return capacity;
        }
        
        /**
         * 如果所需的最小容量大于底层数组elementData的容量大小,进行扩容,否则直接返回
         */
        private void ensureExplicitCapacity(int minCapacity) {
            // 结构性修改次数—+1
            modCount++;
            // 如果所需的最小容量大于elementData的容量,进行扩容
            if(minCapacity - elementData.length > 0) {
                // 进行扩容
                grow(minCapacity);
            }
        }
        
        /**
         * 扩容
         */
        private void grow(int minCapacity) {
            // 当前数组容量
            int oldCapacity = elementData.length;
            // 新数组容量为旧数组容量的1.5倍
            int newCapacity = oldCapacity + (oldCapacity >> 1);
            
            if(newCapacity - minCapacity < 0) {
               // 如果新数组容量还是不够(也有可能是溢出了),赋值新数组容量为所需的最小数组容量
                newCapacity = minCapacity;
            }
            
            if(newCapacity - MAX_ARRAY_SIZE > 0) {
                // 如果新数组容量比MAX_ARRAY_SIZE大,并且所需的minCapacity也大于MAX_ARRAY_SIZE,设置新容量为Integer.MAX_VALUE,否则设置为MAX_ARRAY_SIZE
                newCapacity = hugeCapacity(minCapacity);
            }
            // 将旧数组拷贝到新数组
            elementData = Arrays.copyOf(elementData, newCapacity);
        }
        
        private static int hugeCapacity(int minCapacity) {
            if(minCapacity < 0) {
                throw new OutOfMemoryError();
            }
            return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
        }
        
        
        private void rangeCheck(int index) {
            if(index < 0 || index >= this.size) {
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
            }
        }
        
        private void rangeCheckForAdd(int index) {
            if(index < 0 || index > this.size) {
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
            }
        }
    
        
        
        
    }
    
  • 相关阅读:
    面试题:增强一个对象的方法的三种方式
    Spring笔记01_下载_概述_监听器
    mybatis笔记02
    mybatis笔记01
    muduo学习笔记(二)Reactor关键结构
    Muduo学习笔记(一) 什么都不做的EventLoop
    一个linux下简单的纯C++实现Http请求类(GET,POST,上传,下载)
    一个轻巧高效的多线程c++stream风格异步日志(二)
    一个轻巧高效的多线程c++stream风格异步日志(一)
    C++智能指针,指针容器原理及简单实现(auto_ptr,scoped_ptr,ptr_vector).
  • 原文地址:https://www.cnblogs.com/QullLee/p/11182299.html
Copyright © 2020-2023  润新知