Java集合—ArrayList的源码解读

Java集合—ArrayList的源码解读

ArrayList 概述

ArrayList的是基于数据来实现的,它是一个动态数组,它会自动扩容。ArrayList不是线程安全的,只能用在单线程环境下,多线程环境下可以考虑用 Collections.synchronizedList(List l)函数返回一个线程安全的ArrayList类,也可以使用concurrent并发包下的CopyOnWriteArrayList类,或者Vector。

1 定义
ArrayList 实现了RandmoAccess接口,即提供了随机访问功能。
ArrayList 实现了Cloneable接口,即覆盖了函数clone(),能被克隆。
ArrayList 实现java.io.Serializable接口,这意味着ArrayList支持序列化,能通过序列化去传输。

public class ArrayList<E>
  extends AbstractList<E>
  implements List<E>, RandomAccess, Cloneable, Serializabl 
{

}

2 属性
serialVersionUID 提供序列化的UID,保证不同平台反序列化可以成功。
DEFAULT_CAPACITY 定义ArrayList默认的容器大小。
EMPTY_ELEMENTDATA,DEFAULTCAPACITY_EMPTY_ELEMENTDATA 数组在初始化的时候使用,主要是为了初始化不会另外的创建对象,节约内存使用。
elementData数组用来存储ArrayList元素。需要解释的是transient 关键字:java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。transient是Java语言的关键字,用来表示一个域不是该对象串行化的一部分。当一个对象被串行化的时候,transient型变量的值不包括在串行化的表示中,然而非transient型的变量是被包括进去的。
size 是指数组元素
private static final long serialVersionUID = 8683452581122892189L;
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = new Object[0];
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = new Object[0];
transient Object[] elementData;
private int size;
private static final int MAX_ARRAY_SIZE = 2147483639;

3 构造函数
ArrayList定义了三个构造函数。第一个构造函数是可以指定数组元素大小的,第二个是不带参数的构造函数,它也是我们最常用的一种初始化方式,不申请内存,默认数组大小为0。第三个构造函数使用collection集合来初始化,使之包含collection元素。

public ArrayList(int paramInt)
  {  
    if (paramInt > 0) { // 值得我们学习的是对函数传入参数的判定,保持代码的健壮性
      this.elementData = new Object[paramInt];
    } else if (paramInt == 0) {
      this.elementData = EMPTY_ELEMENTDATA;
    } else {
      throw new IllegalArgumentException("Illegal Capacity: " + paramInt);
    }
  }

  public ArrayList()
  {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
  }

  public ArrayList(Collection<? extends E> paramCollection)
  {
    this.elementData = paramCollection.toArray();
    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 = EMPTY_ELEMENTDATA;
    }
  }
  // 思考 使用new ArrayList() 和 new ArrayList(0)来初始化的区别 ???

解决这个问题则需要明白ArrayList是如何动态扩容的

//ArrayList使用此方法确定数组有足够的大小存储元素
private void ensureCapacityInternal(int paramInt) 
  {
    if (this.elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
      paramInt = Math.max(10, paramInt); //大部分情况下this.elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA时paramInt会小于10,因此当使用new ArrayList()初始化时第一次申请的数组大小为10
    }
    ensureExplicitCapacity(paramInt);
  }

  private void ensureExplicitCapacity(int paramInt)
  {
    this.modCount += 1;
    if (paramInt - this.elementData.length > 0) {//数组的长度不够时,调用grow申请内存
      grow(paramInt);
    }
  }

  private void grow(int paramInt)
  {
    int i = this.elementData.length;//elementData数组的长度
    int j = i + (i >> 1);// 即j = i +i/2 增加原来1/2的长度
    if (j - paramInt < 0) { //如果j< paramInt 则将j赋值围paramInt
      j = paramInt;
    }
    if (j - 2147483639 > 0) { // 判断是否超过最大长度,超过则申请Integer.MAX_VALUE的元素内存
      j = hugeCapacity(paramInt);
    }
    this.elementData = Arrays.copyOf(this.elementData, j);//copyOf方法复制指定的数组,截取或用null填充(如有必要),以使副本具有指定的长度
  }

  private static int hugeCapacity(int paramInt)
  {
    if (paramInt < 0) {
      throw new OutOfMemoryError();
    }
    return paramInt > 2147483639 ? Integer.MAX_VALUE : 2147483639;
  }

回到上面的问题,使用new ArrayList() 和 new ArrayList(0)来初始化的区别?
使用new ArrayList() 第一次调用ensureCapacityInternal时,this.elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA成立,paramInt会被赋予10,,grow函数中由于elementData.length =0 所以i=0,j=0, j-paramInt<0成立,j被赋值为10,Arrays.copyOf(this.elementData, j)第一次申请的数组大小为10.如果使用new ArrayList(0)当第一次调用ensureCapacityInternal函数时,通常传入的参数为1. j最终等于1,只会申请数组大小为1的内存。

**常用方法**
public int size()
  {
    return this.size;//返回size表示数组中包含元素的数量
  }

  public boolean isEmpty()
  {
    return this.size == 0;// size==0 意味elementData中没有存储任何元素
  }

  public boolean contains(Object paramObject)
  {
    return indexOf(paramObject) >= 0;//indexof返回-1表示数组中不包含该对象
  }
  // indexof返回paramObject对象的索引位置。分两种情况,
  // paramObject为null和不为null的情况。
  public int indexOf(Object paramObject)
  {
    int i;
    //如果paramObject为null,则判断数组中是否包含null元素
    if (paramObject == null) {
      for (i = 0; i < this.size; i++) {
        if (this.elementData[i] == null) {
          return i;
        }
      }
    } else {
    //不为空则判断数组中是否存在paramObject对象
      for (i = 0; i < this.size; i++) {
        if (paramObject.equals(this.elementData[i])) {
          return i;
        }
      }
    }
    return -1;
  }
  //反向寻找是否包含paramObject对象
  public int lastIndexOf(Object paramObject)
  {
    int i;
    if (paramObject == null) {
      for (i = this.size - 1; i >= 0; i--) {
        if (this.elementData[i] == null) {
          return i;
        }
      }
    } else {
      for (i = this.size - 1; i >= 0; i--) {
        if (paramObject.equals(this.elementData[i])) {
          return i;
        }
      }
    }
    return -1;
  }

  public Object clone()
  {
    try
    {
      ArrayList localArrayList = (ArrayList)super.clone();
      localArrayList.elementData = Arrays.copyOf(this.elementData, this.size);
      localArrayList.modCount = 0;
      return localArrayList;
    }
    catch (CloneNotSupportedException localCloneNotSupportedException)
    {
      throw new InternalError(localCloneNotSupportedException);
    }
  }
  // 将ArrayList转换为数组
  public Object[] toArray()
  {
    return Arrays.copyOf(this.elementData, this.size);
  }

  public <T> T[] toArray(T[] paramArrayOfT)
  {
    if (paramArrayOfT.length < this.size) {
      return (Object[])Arrays.copyOf(this.elementData, this.size, paramArrayOfT.getClass());
    }
    System.arraycopy(this.elementData, 0, paramArrayOfT, 0, this.size);
    if (paramArrayOfT.length > this.size) {
      paramArrayOfT[this.size] = null;
    }
    return paramArrayOfT;
  }
  //返回数组中位置为paramInt的元素
  E elementData(int paramInt)
  {
    return (E)this.elementData[paramInt];
  }
  // 获得第paramInt位置的元素
  public E get(int paramInt)
  {
    rangeCheck(paramInt);//保证paramInt小于size
    return (E)elementData(paramInt);
  }
  //设置位置paramInt的元素为paramE
  public E set(int paramInt, E paramE)
  { 
    //保证paramInt小于size
    rangeCheck(paramInt);
    Object localObject = elementData(paramInt);
    this.elementData[paramInt] = paramE;
    return (E)localObject;
  }
  //往elementData数组中增加元素paramE
  public boolean add(E paramE)
  { //确保elementData数组足够的空间存放paramE
    ensureCapacityInternal(this.size + 1);
    this.elementData[(this.size++)] = paramE;
    return true;
  }
  //往位置paramInt增加元素paramE
  public void add(int paramInt, E paramE)
  {
    rangeCheckForAdd(paramInt);
    ensureCapacityInternal(this.size + 1);
    System.arraycopy(this.elementData, paramInt, this.elementData, paramInt + 1, this.size - paramInt);
    this.elementData[paramInt] = paramE;
    this.size += 1;
  }
  //移除位置paramInt的元素
  public E remove(int paramInt)
  {
    rangeCheck(paramInt);
    this.modCount += 1;
    Object localObject = elementData(paramInt);
    int i = this.size - paramInt - 1;
    if (i > 0) {
      System.arraycopy(this.elementData, paramInt + 1, this.elementData, paramInt, i);
    }
    this.elementData[(--this.size)] = null;
    return (E)localObject;
  }
  //移除paramObject对象
  public boolean remove(Object paramObject)
  {
    int i;
    if (paramObject == null) {
      for (i = 0; i < this.size; i++) {
        if (this.elementData[i] == null)
        {
          fastRemove(i);
          return true;
        }
      }
    } else {
      for (i = 0; i < this.size; i++) {
        if (paramObject.equals(this.elementData[i]))
        {
          fastRemove(i);
          return true;
        }
      }
    }
    return false;
  }
  //快速移除paramInt的元素
  private void fastRemove(int paramInt)
  {
    this.modCount += 1;
    int i = this.size - paramInt - 1;
    if (i > 0) {
      System.arraycopy(this.elementData, paramInt + 1, this.elementData, paramInt, i);
    }
    this.elementData[(--this.size)] = null;
  }
  //清除数组中的元素
  public void clear()
  {
    this.modCount += 1;
    for (int i = 0; i < this.size; i++) {
      this.elementData[i] = null;
    }
    this.size = 0;
  }
  //讲集合paramCollection中的元素添加到数组中
  public boolean addAll(Collection<? extends E> paramCollection)
  {
    Object[] arrayOfObject = paramCollection.toArray();
    int i = arrayOfObject.length;
    ensureCapacityInternal(this.size + i);
    System.arraycopy(arrayOfObject, 0, this.elementData, this.size, i);
    this.size += i;
    return i != 0;
  }
  //讲paramCollection中的元素添加到位置paramInt后
  public boolean addAll(int paramInt, Collection<? extends E> paramCollection)
  {
    rangeCheckForAdd(paramInt);
    Object[] arrayOfObject = paramCollection.toArray();
    int i = arrayOfObject.length;
    ensureCapacityInternal(this.size + i);
    int j = this.size - paramInt;
    if (j > 0) {
      System.arraycopy(this.elementData, paramInt, this.elementData, paramInt + i, j);
    }
    System.arraycopy(arrayOfObject, 0, this.elementData, paramInt, i);
    this.size += i;
    return i != 0;
  }
  //移除paramInt1到paramInt2的元素
  protected void removeRange(int paramInt1, int paramInt2)
  {
    this.modCount += 1;
    int i = this.size - paramInt2;
    System.arraycopy(this.elementData, paramInt2, this.elementData, paramInt1, i);
    int j = this.size - (paramInt2 - paramInt1);
    for (int k = j; k < this.size; k++) {
      this.elementData[k] = null;
    }
    this.size = j;
  }
  //检查paramInt是否大于数组元素的数量
  private void rangeCheck(int paramInt)
  {
    if (paramInt >= this.size) {
      throw new IndexOutOfBoundsException(outOfBoundsMsg(paramInt));
    }
  }
  //判断paramInt的范围是否在(0,size)间
  private void rangeCheckForAdd(int paramInt)
  {
    if ((paramInt > this.size) || (paramInt < 0)) {
      throw new IndexOutOfBoundsException(outOfBoundsMsg(paramInt));
    }
  }

  private String outOfBoundsMsg(int paramInt)
  {
    return "Index: " + paramInt + ", Size: " + this.size;
  }
  //从列表中移除指定 collection 中包含的其所有元素
  public boolean removeAll(Collection<?> paramCollection)
  {
    Objects.requireNonNull(paramCollection);
    return batchRemove(paramCollection, false);
  }
  //取得paramCollection和ArraList**重点内容**的交集
  public boolean retainAll(Collection<?> paramCollection)
  {
    Objects.requireNonNull(paramCollection);
    return batchRemove(paramCollection, true);
  }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值