集合--ArrayList篇

1.结构简介

在这里插入图片描述

  1. ArrayList实现了List接口,继承了AbstractList抽象类;
  2. 底层实基于Object数组实现容量大小动态变化;
  3. 允许null值存在;
  4. 同时还实现了RandomAccess,Cloneable,Serializable接口,所以ArrayList支持快速访问、复制、序列化。

2.成员变量

private static final int DEFAULT_CAPACITY = 10;  //数组默认初始容量
private static final Object[] EMPTY_ELEMENTDATA = {}; //指定初始容量为0时的实例对象
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //空参的实例对象
private transient Object[] elementData;   //数组
private int size;  //当前数组包含元素数

AbstractList中有个modCount参数:记录List操作次数,使用在Iterator,防止迭代过程中集合被修改。

3.构造方法

  1. 构造一个空列表
public ArrayList() {
	this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
  1. 构造具有指定容量的空列表
public ArrayList(int initialCapacity) {
	if (initialCapacity > 0) {
		this.elementData = new Object[initialCapacity];
	} else if (initialCapacity == 0) {
		this.elementData = EMPTY_ELEMENTDATA;
	} else {
		throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);
	}
}
  1. 构造一个包含指定集合元素的列表
public ArrayList(Collection<? extends E> c) {
	elementData = c.toArray();
	if ((size = elementData.length) != 0) {
    // c.toArray might (incorrectly) not return Object[] (see 6260652)
    if (elementData.getClass() != Object[].class)
    	elementData = Arrays.copyOf(elementData, size, Object[].class);
	} else {
    	// replace with empty array.
    	this.elementData = EMPTY_ELEMENTDATA;
	}
}

4.扩容

4.1 源码

add(E e)

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

ensureCapacityInternal(int minCapacity)

private void ensureCapacityInternal(int minCapacity) {
  	if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    ensureExplicitCapacity(minCapacity);
}

ensureExplicitCapacity(int minCapacity)

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;
    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

grow(int 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);
}

4.2 源码分析

在这里插入图片描述

4.3 总结

  1. 若是无参初始化ArrayList,首次add后数组容量会变更为DEFAULT_CAPACITY=10。
  2. 当add后的size(即size+1)大于当前数组长度时,则会进行1.5倍[算法公式:length+(length>>1)]扩容。
  3. 扩容的容量大小必须在add后size(即size+1)与MAX_ARRAY_SIZE之间。
  4. 扩容时是使用Arrays.copyof()新建一个容量数组,原数组被GC回收。

5.版本差异

5.1 new ArrayList()初始化差异

  1. JDK1.6及之前:初始容量为10的数组对象。
  2. JDK1.7:elementData=EMPET_ELEMENTDATE({})初始容量为0;首次add时再懒初始化至10。
  3. JDK1.8:elementData=DEFAULT_EMPTY_ELEMENTDATA({})初始容量为0;首次add时再懒初始化至10。
    区别于jdk1.7,ArrayList()时,赋值的是DEFAULTCAPACITY_EMPTY_ELEMENTDATA空数组对象, ArrayList(0)时赋值的是EMPTY_ELEMENTDATA空数组对象。这么代码是为了ArrayList(0)能重用空数组常量EMPTY_ELEMENTDATA,减少new Object[0]操作,降低内存消耗。
JDK1.7:
public ArrayList(int initialCapacity) {
    super();
      if (initialCapacity < 0)
          throw new IllegalArgumentException("Illegal Capacity: "+
                                             initialCapacity);
      this.elementData = new Object[initialCapacity];
}
JDK1.8:
public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
         this.elementData = new Object[initialCapacity];
     } else if (initialCapacity == 0) {
         this.elementData = EMPTY_ELEMENTDATA;
     } else {
         throw new IllegalArgumentException("Illegal Capacity: "+
                                            initialCapacity);
     }
 }

5.2 扩容差异

  1. JDK1.6及之前: (length*3)/2+1
  2. JDK1.7及之后:length+(length>>1) [>>1相比/2:速度快,而且占用资源少,也避免过早出现int溢出的情况。]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值