Java ArrayList 源码解析

66 阅读5分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

  ArrayList  是List 接口可调整大小的数据组实现.

数组: 一旦初始化,数组的长度是不可以发生改变的.

数据查询快,根据地址和索引直接获取元素

数组增删慢,每次都需要创建新数组,且移动元素位置

特点: 

增删慢:每次删除元素,都需要更改数组长度,拷贝及移动元素位置

查询快:由于数组在内存中是一块连续的空间,可以根据地址和索引的方式获取元素上的位置


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

从上边可以看到, ArrayList 继承了 AbstractList 类 实现了 List, RandomAccess,Cloneable,Serializable 这四个接口

1.
public interface RandomAccess {
}

2.
public interface Cloneable {
}
3.
public interface Serializable {
}

从源码上可以看到,以上三个接口都是标识接口,没有起对应的方法或属性

Serializable 序列化的简介:

类是否序列化, 是由是否实现java.io.Serializable 接口来控制的,

1.没有实现该接口的类,将不会进行序列化或反序列化的操作;

  1. 实现了该接口的类, 该类 及其所用子类都是可以序列化的.当然也可以控制某个属性不进行序列化 ,可使用变量修饰符  transient

eg:

private transient String sex;

3.该序列化接口没有方法和属性,仅用户表示可串行化的语义 

RandomAccess 随机访问接口说明:

  Marker interface used by <tt>List</tt> implementations to indicate that
  they support fast (generally constant time) random access.  The primary
  purpose of this interface is to allow generic algorithms to alter their
  behavior to provide good performance when applied to either random or
  sequential access lists.
 
  <p>The best algorithms for manipulating random access lists (such as
  <tt>ArrayList</tt>) can produce quadratic behavior when applied to
  sequential access lists (such as <tt>LinkedList</tt>).  Generic list
  algorithms are encouraged to check whether the given list is an
  <tt>instanceof</tt> this interface before applying an algorithm that would
  provide poor performance if it were applied to a sequential access list,
  and to alter their behavior if necessary to guarantee acceptable
  performance.
 
  <p>It is recognized that the distinction between random and sequential
  access is often fuzzy.  For example, some <tt>List</tt> implementations
  provide asymptotically linear access times if they get huge, but constant
  access times in practice.  Such a <tt>List</tt> implementation
  should generally implement this interface.  As a rule of thumb, a
  <tt>List</tt> implementation should implement this interface if,
  for typical instances of the class, this loop:
  <pre>
      for (int i=0, n=list.size(); i &lt; n; i++)
          list.get(i);
  </pre>
  runs faster than this loop:
  <pre>
      for (Iterator i=list.iterator(); i.hasNext(); )
          i.next();
  </pre>
 
  <p>This interface is a member of the
  <a href="{@docRoot}/../technotes/guides/collections/index.html">
  Java Collections Framework</a>.

翻译如下:

由List实现使用的标记接口,用于指示 它们支持快速(通常是恒定时间)随机访问。初选

此接口的目的是允许通用算法更改其应用于随机或 顺序访问列表。

处理随机访问列表的最佳算法(例如

当应用于 顺序访问列表(如LinkedList)。鼓励通用列表算法在应用如果将其应用于顺序访问列表之前提供交叉性能的算法时,检查给定列表是否 instanceof,并在必要时更改行为以保证可接受的性能.

人们认识到随机和顺序的区别访问通常是模糊的。例如,一些List列表实现
提供渐近线性访问时间,如果它们在时间中获取巨大但是恒定的访问时间。这样的一个List实现通常应该实现这个接口。根据经验,List实现应用此接口,如果对于磊的经典实例,此循环:

for(int i=0,n=list.size();i&lt;n;i++)
    list.get(i);


运行速度超过此循环:

 for (Iterator i=list.iterator(); i.hasNext(); )
         i.next();

ArrayList无参构造,默认初始化为0, 并非说的默认初始化为10 的数组

ArrayList arrayList = new ArrayList();

 public class ArrayList<E> {
     
    // 默认容量为空的数组,长度为0 
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    // 真正存储数据的容器
    transient Object[] elementData; 
 
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

 }
 
 

 ArrayList 有参构造器:

ArrayList arrayList = new ArrayList(8);

   
    private static final Object[] EMPTY_ELEMENTDATA = {};

    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            // 初始化容量 大于0 则创建一个 initialCapacity 容量大小的数据
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            // 初始化容量小于 0 ,则调用空数组
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            // 否则的话会抛出异常
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

 

ArrayList有参构造器: ArrayList(Collection<? extends E> c)

ArrayList arrayList = new ArrayList();

ArrayList arrayList2 = new ArrayList(arrayList);

可以看出这是一个单列集合构造器 (单列集合:顶层集合Collection接口)

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

    public ArrayList(Collection<? extends E> c) {
        // 将集合转为数组
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // 
            if (elementData.getClass() != Object[].class)
                // 数组的创建与拷贝
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // 替换成一个空数组
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

    public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }

}

// 调取的是Collection接口的toArray,实际走的是 ArrayList的toArray() 方法
public interface Collection<E> extends Iterable<E> {
   Object[] toArray();

}

public class Arrays { 
  
     public static <T> T[] copyOf(T[] original, int newLength) {
        // 再次调用copyOf 的到一个数组
        return (T[]) copyOf(original, newLength, original.getClass());
    }
    
     public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
        @SuppressWarnings("unchecked")
        //  都会创建一个新的数组, 且新数组的长度一定是和入参集合的size()式样
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        //  数组的 拷贝
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        // 返回新的数组
        return copy;
    }
}

ArrayList.add() 源码:

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{  
  
  transient Object[] elementData;   

  public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
  }
 
   private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
   }

   private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // 只有容量不够的时候才会调用扩容的方法,不是很次都调用的
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
   // 扩容的核心算法: 原容量的1.5倍
   private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        // >> : 右移 , you右移几位相当于除以2的几次幂
        // 原容量的1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 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);
    }
   
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }
}

 ArrayList.addAll(Collection<? extends E> c)

ArrayList arrayList = new ArrayList();
arrayList.add("test1");
arrayList.add("test2");
ArrayList arrayList2 = new ArrayList();
arrayList2.addAll(arrayList);
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    private int size;
    transient Object[] elementData;
    // 默认初始化容量
    private static final int DEFAULT_CAPACITY = 10;

    public boolean addAll(Collection<? extends E> c) {
        // 把集合转换成数组
        Object[] a = c.toArray();
        // 数组的长度 赋值给新的变量
        int numNew = a.length;
        //  检查及扩容
        ensureCapacityInternal(size + numNew);  // Increments modCount
        // 拷贝数组
        System.arraycopy(a, 0, elementData, size, numNew);
       // 集合长度进行更改
        size += numNew;
        // 根据 numNew的值 返回是否成功
        return numNew != 0;
    }

    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
    
     private static int calculateCapacity(Object[] elementData, int minCapacity) {
        // 如果数组为空,则 比较 默认容量10 与 入参的 容量去最大
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
     }
     
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

}

ArrayList.add(int index, E element) 源码: 在此列表指定位置,插入指定元素


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++;
}

    private void rangeCheckForAdd(int index) {
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

   private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

  
  private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
  
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 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);
    }

ArrayList.addAll(int index, Collection<? extends E> c)


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

    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;
        // 判断需要移动的个数是否大于0 
        if (numMoved > 0)
            // 移动数组位置
            System.arraycopy(elementData, index, elementData, index + numNew,
                             numMoved);
 
        // 将数据源的 集合 添加到目标集合中
        System.arraycopy(a, 0, elementData, index, numNew);
        size += numNew;
        return numNew != 0;
    }
    
     private void rangeCheckForAdd(int index) {
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
     }
    
     private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
     }

 

     private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
     }
         private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
     }
     
      private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 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);
    }
    
     private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

}

ArrayList .set(int index, E element)
ArrayList arrayList = new ArrayList();
arrayList.add("test1");
arrayList.add("test2");
ArrayList arrayList2 = new ArrayList();
arrayList2.set(2,"test");


   public E set(int index, E element) {
        rangeCheck(index);

        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }
   
    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

     E elementData(int index) {
        return (E) elementData[index];
    }

ArrayList E get(int index);

ArrayList arrayList = new ArrayList();
arrayList.add("test1");
arrayList.add("test2");
arrayList.get(1);


 public E get(int index) {
        rangeCheck(index);

        return elementData(index);
    }

 private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

  E elementData(int index) {
        return (E) elementData[index];
    } 

\