深入学习java8集合(一):ArrayList的实现原理

匿名 (未验证) 提交于 2019-12-02 21:53:52

  ArrayList是List接口的可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。
  
  每个ArrayList实例都有一个容量,该容量是指用来存储列表元素的数组的大小。它总是至少等于列表的大小。随着向ArrayList中不断添加元素,其容量也自动增长。自动增长会带来数据向新数组的重新拷贝,因此,如果可预知数据量的多少,可在构造ArrayList时指定其容量。在添加大量元素前,应用程序也可以使用ensureCapacity操作来增加ArrayList实例的容量,这可以减少递增式再分配的数量。
  
  注意,此实现不是同步的。如果多个线程同时访问一个ArrayList实例,而其中至少一个线程从结构上修改了列表,那么它必须保持外部同步。(结构上的修改是指任何添加或删除一个或多个元素的操作,或者显式调整底层数组的大小;仅仅设置元素的值不是结构上的修改。)这一般通过对自然封装该列表的对象进行同步操作来完成。如果不存在这样的对象,则应该使用 Collections.synchronizedList 方法将该列表“包装”起来。这最好在创建时完成,以防止意外对列表进行不同步的访问:

List list = Collections.synchronizedList(new ArrayList(...)); 

  此类的 iterator 和 listIterator 方法返回的迭代器是快速失败的:在创建迭代器之后,除非通过迭代器自身的 remove 或 add 方法从结构上对列表进行修改,否则在任何时间以任何方式对列表进行修改,迭代器都会抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就会完全失败,而不是冒着在将来某个不确定时间发生任意不确定行为的风险。
  
  注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。快速失败迭代器会尽最大努力抛出 ConcurrentModificationException。因此,为提高这类迭代器的正确性而编写一个依赖于此异常的程序是错误的做法:迭代器的快速失败行为应该仅用于检测 bug。
  此类是 Java Collections Framework 的成员。

对于ArrayList而言,它实现List接口、底层使用数组保存所有元素。其操作基本上是对数组的操作。下面我们来分析ArrayList的源代码:
1)底层使用数组实现:

 /**    * The array buffer into which the elements of the ArrayList are stored.    * The capacity of the ArrayList is the length of this array buffer. Any    * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA    * will be expanded to DEFAULT_CAPACITY when the first element is added.    */    transient Object[] elementData; // non-private to simplify nested class access

2)构造方法:
  ArrayList提供了三种构造器

方法 说明
ArrayList() 构造一个初始容量为 10 的空列表。
ArrayList(Collection c) 构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection 的迭代器返回它们的顺序排列的。
ArrayList(int initialCapacity) 构造一个具有指定初始容量的空列表。

3)存储
   ArrayList提供了set(int index, E element)、add(E e)、add(int index, E element)、addAll(Collection

//用指定的元素替代此列表中指定位置上的元素。 public E set(int index, E element) {      rangeCheck(index);       E oldValue = elementData(index);      elementData[index] = element;      return oldValue;  } //将指定的元素添加到此列表的尾部。 public boolean add(E e) {      ensureCapacityInternal(size + 1);  // Increments modCount!!      elementData[size++] = e;      return true; } //将指定的元素插入此列表中的指定位置。如果当前位置有元素,则向右移动当前位于该位置的元素以及所有后续元素(将其索引加1)。   public void add(int index, E element) {       rangeCheckForAdd(index);        ensureCapacityInternal(size + 1);  // Increments modCount!!       System.arraycopy(elementData, index, elementData, index + 1, size - index);       elementData[index] = element;       size++; }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!