1. public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable

从ArrayList<E>可以看出它是支持泛型的,它继承自AbstractList,实现了List、RandomAccess、Cloneable、java.io.Serializable接口。

AbstractList提供了List接口的默认实现(个别方法为抽象方法)。

List接口定义了列表必须实现的方法。

RandomAccess是一个标记接口,接口内没有定义任何内容。

实现了Cloneable接口的类,可以调用Object.clone方法返回该对象的浅拷贝。

通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。序列化接口没有方法或字段,仅用于标识可序列化的语义。

ArrayList几个重要的字段属性

  1. private static final int DEFAULT_CAPACITY = 10;
  2.  
  3. /**
  4. * Shared empty array instance used for empty instances.
  5. */
  6. private static final Object[] EMPTY_ELEMENTDATA = {};
  7.  
  8. /**
  9. * Shared empty array instance used for default sized empty instances. We
  10. * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
  11. * first element is added.
  12. */
  13. private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
  14. // 存储ArrayList的元素
  15. transient Object[] elementData; // non-private to simplify nested class access
  16.  
  17. /**
  18. * The size of the ArrayList (the number of elements it contains).
  19. *
  20. * @serial
  21. */
  22. // elementData指示elementData包含的元素的数量
  23. private int size;
  1. private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

ArrayList的构造方法:

  1. public ArrayList(int initialCapacity) {
  2. if (initialCapacity > 0) {
  3. this.elementData = new Object[initialCapacity];
  4. } else if (initialCapacity == 0) {
  5. // this.elementData = {};
  6. this.elementData = EMPTY_ELEMENTDATA;
  7. } else {
  8. throw new IllegalArgumentException("Illegal Capacity: "+
  9. initialCapacity);
  10. }
  11. }
  12.  
  13. /**
  14. * Constructs an empty list with an initial capacity of ten.
  15. */
  16. public ArrayList() {
  17. this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
  18. }
  19.  
  20. // 使用集合来初始化
  21. public ArrayList(Collection<? extends E> c) {
  22. elementData = c.toArray();
  23. if ((size = elementData.length) != 0) {
  24. // c.toArray might (incorrectly) not return Object[] (see 6260652)
  25. if (elementData.getClass() != Object[].class)
  26. elementData = Arrays.copyOf(elementData, size, Object[].class);
  27. } else {
  28. // replace with empty array.
  29. this.elementData = EMPTY_ELEMENTDATA;
  30. }
  31. }

第一个构造方法:根据指定容量进行构造elementData数组。

第二个无参构造方法:初始化为{},size也为0.当执行add操作的时候,如果为{},则将其容量初始化为DEFAULT_CAPACITY,即为10

第三个构造方法:将集合对象转换成Object数组。Arrays的方法在另一篇博文将做分析。

其它方法:

add(E e):

  1. public boolean add(E e) {
  2. // 扩容
  3. ensureCapacityInternal(size + 1); // Increments modCount!!
  4. elementData[size++] = e;
  5. return true;
  6. }
  1. private void ensureCapacityInternal(int minCapacity) {
  2. ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
  3. }
  1. private static int calculateCapacity(Object[] elementData, int minCapacity) {
         // 如果elementData为空,则初始化为DEFAULT_CAPACITY
  2. if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
  3. return Math.max(DEFAULT_CAPACITY, minCapacity);
  4. }
  5. return minCapacity;
  6. }
  1. private void ensureExplicitCapacity(int minCapacity) {
  2. modCount++;
  3.  
  4. // overflow-conscious code , 如果扩容大于elementData容量,进行扩容。
  5. if (minCapacity - elementData.length > 0)
  6. grow(minCapacity);
  7. }
  1. private void grow(int minCapacity) {
  2. // overflow-conscious code
  3. int oldCapacity = elementData.length;
  4. // newCapacity = oldCapacity * 1.5 扩大为之前的1.5倍。
  5. int newCapacity = oldCapacity + (oldCapacity >> 1);
  6. if (newCapacity - minCapacity < 0)
  7. // 如果扩容后,newCapacity还是小于minCapacity,则直接赋值为minCapacity
  8. newCapacity = minCapacity;
         // 如果1.5 * elementData.length比Integer.MAX_VALUE - 8还大
  9. if (newCapacity - MAX_ARRAY_SIZE > 0)
  10. newCapacity = hugeCapacity(minCapacity);
  11. // minCapacity is usually close to size, so this is a win:
  12. elementData = Arrays.copyOf(elementData, newCapacity);
  13. }
  1. private static int hugeCapacity(int minCapacity) {
  2. if (minCapacity < 0) // overflow
  3. throw new OutOfMemoryError();
         // 如果minCapacity即为Array.length大于Integer.MAX_VALUE - 8. 则直接赋为Integer.MAX_VALUE , 否则就为MAX_ArraySIZE
  4. return (minCapacity > MAX_ARRAY_SIZE) ?
  5. Integer.MAX_VALUE :
  6. MAX_ARRAY_SIZE;
  7. }

为什么是1.5倍扩容呢?

  1. public boolean addAll(Collection<? extends E> c)

先将集合c转换成数组,根据转换后数组的程度和ArrayList的size拓展容量,之后调用System.arraycopy方法复制元素到elementData的尾部,调整size。根据返回的内容分析,只要集合c的大小不为空,即转换后的数组长度不为0则返回true。

  1. public boolean addAll(int index, Collection<? extends E> c)

先判断index是否越界。其他内容与addAll(Collection<? extends E> c)基本一致,只是复制的时候先将index开始的元素向后移动X(c转为数组后的长度)个位置(也是一个复制的过程),之后将数组内容复制到elementData的index位置至index+X。

clear的时候并没有修改elementData的长度(好不容易申请、拓展来的,凭什么释放,留着搞不好还有用呢。这使得确定不再修改list内容之后最好调用trimToSize来释放掉一些空间),只是将所有元素置为null,size设置为0。

  1. public void clear() {
  2. modCount++;
  3.  
  4. // clear to let GC do its work
  5. for (int i = 0; i < size; i++)
  6. elementData[i] = null;
  7.  
  8. size = 0;
  9. }

返回此 ArrayList 实例的浅表副本。(不复制这些元素本身。),如果是对象,只是复制引用。

  1. public Object clone() {
  2. try {
  3. ArrayList<?> v = (ArrayList<?>) super.clone();
  4. v.elementData = Arrays.copyOf(elementData, size);
  5. v.modCount = 0;
  6. return v;
  7. } catch (CloneNotSupportedException e) {
  8. // this shouldn't happen, since we are Cloneable
  9. throw new InternalError(e);
  10. }
  11. }

indexOf:通过遍历elementData数组来判断对象是否在list中,若存在,返回元素下标的位置。时间复杂度是O(n)

  1. public int indexOf(Object o) {
  2. if (o == null) {
  3. for (int i = 0; i < size; i++)
  4. if (elementData[i]==null)
  5. return i;
  6. } else {
  7. for (int i = 0; i < size; i++)
  8. if (o.equals(elementData[i]))
  9. return i;
  10. }
  11. return -1;
  12. }

lastIndexOf:从后向前遍历。

remove:

  1. public E remove(int index) {
  2. rangeCheck(index);
  3.  
  4. modCount++;
  5. E oldValue = elementData(index);
  6.  
  7. int numMoved = size - index - 1;
  8. if (numMoved > 0)
  9. // 从index+1开始的元素复制到elementData中从index下标开始,总共有numMoved个元素。
  10. System.arraycopy(elementData, index+1, elementData, index,
  11. numMoved);
  12. elementData[--size] = null; // clear to let GC do its work
  13.  
  14. return oldValue;
  15. }
  1. public boolean remove(Object o) {
  2. if (o == null) {
  3. for (int index = 0; index < size; index++)
  4. if (elementData[index] == null) {
  5. // fastRemove基本和remove的代码一致,只是不用进行边界判断。
  6. fastRemove(index);
  7. return true;
  8. }
  9. } else {
  10. for (int index = 0; index < size; index++)
  11. if (o.equals(elementData[index])) {
  12. fastRemove(index);
  13. return true;
  14. }
  15. }
  16. return false;
  17. }

ArrayList源码分析(基于JDK1.8)的更多相关文章

  1. ArrayList 源码分析 基于jdk1.8:

    1:数据结构: transient Object[] elementData;  //说明内部维护的数据结构是一个Object[] 数组 成员属性: private static final int ...

  2. HashMap 源码分析 基于jdk1.8分析

    HashMap 源码分析  基于jdk1.8分析 1:数据结构: transient Node<K,V>[] table;  //这里维护了一个 Node的数组结构: 下面看看Node的数 ...

  3. CopyOnWriteArrayList 源码分析 基于jdk1.8

    CopyOnWriteArrayList  源码分析: 1:成员属性: final transient ReentrantLock lock = new ReentrantLock();  //内部是 ...

  4. ArrayList 源码分析(JDK1.8)

    ArrayList简介  ArrayList 是一个数组队列,相当于 动态数组.与Java中的数组相比,它的容量能动态增长.它继承于AbstractList,实现了List, RandomAccess ...

  5. ArrayList源码分析(JDK1.8)

    概述 ArrayList底层是基于数组实现的,并且支持动态扩容的动态数组(变长的集合类).ArrayList允许空值和重复的元素,当向ArrayList中添加元素数量大于其底层数组容量时,会通过扩容机 ...

  6. HashMap源码分析-基于JDK1.8

    hashMap数据结构 类注释 HashMap的几个重要的字段 hash和tableSizeFor方法 HashMap的数据结构 由上图可知,HashMap的基本数据结构是数组和单向链表或红黑树. 以 ...

  7. ArrayList的源码分析(基于jdk1.8)

    1.初始化 transient Object[] elementData; //实际存储元素的数组 private static final Object[] DEFAULTCAPACITY_EMPT ...

  8. LinkedList的源码分析(基于jdk1.8)

    1.初始化 public LinkedList() { } 并未开辟任何类似于数组一样的存储空间,那么链表是如何存储元素的呢? 2.Node类型 存储到链表中的元素会被封装为一个Node类型的结点.并 ...

  9. ArrayList源码解读(jdk1.8)

    概要 上一章,我们学习了Collection的架构.这一章开始,我们对Collection的具体实现类进行讲解:首先,讲解List,而List中ArrayList又最为常用.因此,本章我们讲解Arra ...

  10. ArrayList源码分析--jdk1.8

    ArrayList概述   1. ArrayList是可以动态扩容和动态删除冗余容量的索引序列,基于数组实现的集合.  2. ArrayList支持随机访问.克隆.序列化,元素有序且可以重复.  3. ...

随机推荐

  1. nginx与apache 对比 apache是同步多进程模型,一个连接对应一个进程;nginx是异步的,多个连接(万级别)可以对应一个进程

    nginx与apache详细性能对比 http://m.blog.csdn.net/lengzijian/article/details/7699444 http://www.cnblogs.com/ ...

  2. XMU 1615 刘备闯三国之三顾茅庐(三) 【欧拉函数+快速幂+欧拉定理】

    1615: 刘备闯三国之三顾茅庐(三) Time Limit: 1000 MS  Memory Limit: 128 MBSubmit: 45  Solved: 8[Submit][Status][W ...

  3. +Java中的native关键字浅析(Java+Native+Interface)++

    JNI是Java Native Interface的 缩写.从Java 1.1开始,Java Native Interface (JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的 ...

  4. 高清摄像头MIPI CSI2接口浅解【转】

    本文转载自:http://blog.csdn.net/u012075739/article/details/44672435 MIPI摄像头常见于手机.平板中,支持500万像素以上高清分辨率.它的全称 ...

  5. silverlight DataGrid 显示篇

    silverlight DataGrid 显示篇 分类: Silverlight2012-05-12 21:55 693人阅读 评论(0) 收藏 举报 datagridsilverlightbindi ...

  6. Masonry 比例(multipliedBy)

    前言 说到iOS自动布局,有很多的解决办法.有的人使用xib/storyboard自动布局,也有人使用frame来适配.对于前者,笔者并不喜欢,也不支持.对于后者,更是麻烦,到处计算高度.宽度等,千万 ...

  7. iOS开发,#define的使用

    1.判断当前设备是不是iOS7以上版本 #define IOS_VERSION_7_OR_ABOVE (([[[UIDevice currentDevice] systemVersion] float ...

  8. jquery中跳出each循环

    or循环   VS   jquery.each continue       return true break          return false

  9. Jmeter测试接口

    文主要针对http接口进行测试,使用Jmeter工具实现. Jmter工具设计之初是用于做性能测试的,它在实现对各种接口的调用方面已经做的比较成熟,因此,本次直接使用Jmeter工具来完成对Http接 ...

  10. CCF2016.4 - A题

    思路:枚举每个点,看看它是否同时小于/大于前一个点和后一个点 import java.util.Scanner; public class Main { public static void main ...