ArrayList 源码分析

 

1)ArrayList 特点

  • List 接口的可变数组实现,ArrayList 允许使用任何元素,包括 null。
  • ArrayList 和 Vector 基本类似,只不过 Vector 是线程安全的,ArrayList 是线程不安全的。
  • size、isEmpty、get、set、iterator 和 listIterator 以常量时间运行,其他的操作基本以线性时间运行。
  • 每个 ArrayList 都有一个容量,容量表示该 ArrayList 当前能容纳的元素个数,随着元素的增加,ArrayList 会自动扩容。
  • 在创建 ArrayList 时可以指定一个合适的初始化容量,以减少频繁扩容带来的性能损耗。
  • ArrayList 是线程不安全的,多线程并发访问 ArrayList 并且至少有一个线程修改了它的结构【增加、删除元素、扩容等】,
    则 ArrayList 将抛出 ConcurrentModificationException 异常。
  • 快速失败机制:iterator 和 listIterator 返回的迭代器是快速失败的,如果不是通过 ListIterator#remove() 或 ListIterator#add(Object) 方法修改其结构,
    则 ArrayList 将尽最大努力抛出 ConcurrentModificationException 异常。
  • ArrayList 的缩容机制:通过 trimToSize 方法将 ArrayList 的容量缩小为当前元素的个数,以减少 ArrayList 的内存占用。
  • ArrayList 的扩容机制:默认为 1.5 倍向下取整扩容,如果批量添加元素,则以 size+newNum 进行扩容。

2)创建实例

    /**      * ArrayList 底层存储元素的数组缓冲区      */     transient Object[] elementData;      // 用于在空实例之间共享的空对象数组,用于简化扩容实现     private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};          // 创建容量为 10 的空 ArrayList 实例     public ArrayList() {         this.elementData = ArrayList.DEFAULTCAPACITY_EMPTY_ELEMENTDATA;     }      /**      * 基于用户指定的容量创建空 ArrayList 实例      */     public ArrayList(int initialCapacity) {         if (initialCapacity > 0) {             // 创建指定大小的对象数组             this.elementData = new Object[initialCapacity];         } else if (initialCapacity == 0) {             // 使用共享的空数组             this.elementData = ArrayList.EMPTY_ELEMENTDATA;         } else {             throw new IllegalArgumentException("Illegal Capacity: "+                     initialCapacity);         }     }      /**      * 基于指定的集合创建 ArrayList 实例      */     public ArrayList(Collection<? extends E> c) {         // 集合转化为对象数组         this.elementData = c.toArray();         /**          * 集合容量不为 0,并且类型不是 Object[].class,则将其转换为对象数组。          */         if ((this.size = this.elementData.length) != 0) {             if (this.elementData.getClass() != Object[].class) {                 this.elementData = Arrays.copyOf(this.elementData, this.size, Object[].class);             }         } else {             // 空集合默认使用共享空数组             this.elementData = ArrayList.EMPTY_ELEMENTDATA;         }     }

3)在尾部添加元素

    /**      *  【modCount 属性定义在 AbstractList 中】      *  【ArrayList 被结构化修改的次数,结构化修改主要是改变 List 大小的操作】      *  【该属性主要被 {@code iterator} and {@code listIterator} 方法返回的迭代器使用,      *  用于在迭代器遍历元素时阻止并发修改带来的数据错误,如果此字段的值发生意外的更改,      *  则迭代器将抛出 ConcurrentModificationException 异常。      *  它实现了在列表出现并发修改时的快速失败机制。】      */     protected transient int modCount = 0;      /**      * 在 ArrayList 尾部新增元素      */     @Override     public boolean add(E e) {         modCount++;         this.add(e, this.elementData, this.size);         return true;     }      /**      * 将方法字节码控制在 35(the -XX:MaxInlineSize default value) 个之内,以实现预编译和内联。      */     private void add(E e, Object[] elementData, int s) {         // 如果当前元素个数和底层数组长度一致,则需要执行扩容         if (s == elementData.length) {             elementData = this.grow();         }         // 插入元素         elementData[s] = e;         // 增加元素个数         this.size = s + 1;     }      /**      * 默认每次增加一个空间,触发 1.5 倍向下取整扩容      */     private Object[] grow() {         return this.grow(this.size + 1);     }      /**      * 增加 ArrayList 的容量以满足最少能容纳 minCapacity 个元素      */     private Object[] grow(int minCapacity) {         // 基于数组拷贝实现扩容         return this.elementData = Arrays.copyOf(this.elementData,                 this.newCapacity(minCapacity));     }      /**      * 可分配的最大数组大小      */     private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;      /**      * 基于预期容量计算新的容量      */     private int newCapacity(int minCapacity) {         // overflow-conscious code         final int oldCapacity = this.elementData.length;         /**          * 1.5 倍向下取整扩容          */         final int newCapacity = oldCapacity + (oldCapacity >> 1);         /**          * 默认扩容后的容量小于预期容量,则以预期容量为准          */         if (newCapacity - minCapacity <= 0) {             // 第一次扩容时,取 10 和 minCapacity 的最大值             if (this.elementData == ArrayList.DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {                 return Math.max(ArrayList.DEFAULT_CAPACITY, minCapacity);             }             // 预期容量溢出          
                    
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信