ArrayList源码解析(部分)

ArrayList基本构成以及动态扩容机制

一.静态Filed和实例Filed解析

1.private static final int DEFAULT_CAPACITY = 10**(线程共享,默认容量)**:初始化默认值为10,默认容量,用于动态扩容。

2.private static final Object[] EMPTY_ELEMENTDATA = {}(线程共享,类存在的属性):共享的空对象数组,未指定容量,类自身存在的属性,是所有实例共享的。

3.private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
注:类 的 Field 指的 默认的容量_空的_元素数据 Object[] 数组引用 ,是指定了容量,但是为空的实例;

4.transient Object[] elementData (实例属性,线程不共享): transient 标识 数据在 Serializable(序列化的)会被忽略 真实值 ,
从而初始化 成默认值 基本数据类型 默认 0 ,引用类型默认null。

5.private int size :指定实例所保存元素的个数

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    private static final long serialVersionUID = 8683452581122892189L;//UUID 序列化时唯一标识

    /**
     * Default initial capacity.
     */
    private static final int DEFAULT_CAPACITY = 10;//默认容量

    /**
     * Shared empty array instance used for empty instances.
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};//所有未指定容量的空实例的共同指向的实例

    /**
     * Shared empty array instance used for default sized empty instances. We
     * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
     * first element is added.
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//定义了容量但是元素个数为空的实例共同指向的实例

    /**
     * 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
	//transient: 代表当对象序列化的时候,不被序列化,这个Field 是用来分配每个实例存储元素的空间
    /**
     * The size of the ArrayList (the number of elements it contains).
     *
     * @serial
     */
    private int size;
    //记录当前元素的个数

二.构造方法设计

1.带有一个参数 initialCapacity 初始化容量:
当选择 initialCapacity == 0 ,存放元素的 elementData 会使用 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 指定的空间,也就是初始化 EMPTY_ELEMENTDATA

    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {//当指定了初始容量时,直接创建数组初始化elementData
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;//等于零时,当作没有容量但是为空的实例处理 指向EMPTY_ELEMENTDATA
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

2.无参构造器: 直接 使用DEFAULTCAPACITY_EMPTY_ELEMENTDATA 初始化 elementData

   public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;//DEFAULTCAPACITY_EMPTY_ELEMENTDATA未指定容量,实例数据为空
    }

3.带有一个Collection<? extents E> 引用 参数 的构造方法 :
Collection<? extends E> c:声明接口类型,在运行时确定真实类型

	public ArrayList(Collection<? extends E> c) {
        Object[] a = c.toArray();  // 将对应的集合类型的值转换 成数组类型
        if ((size = a.length) != 0) { // 初始化 size值
            if (c.getClass() == ArrayList.class) { // 因为 ArrayList 也是 Collection的一个实现类 ,所以判断当前实例类型是否是ArraList类型,如果是c.toArray() 采用的就是ArrayList重写的toArray方法 已经完成了 类型检验  ,所以可以忽略对a的类型检验
                elementData = a; //如果是,可以直接 将  a 作为elementData 的初始化值
            } else {
                elementData = Arrays.copyOf(a, size, Object[].class); //否则要通过 对a进行类型检验 
            }
        } else {
            // replace with empty array.
            elementData = EMPTY_ELEMENTDATA;//让当前引用指向同一为空的数组,所有空实例共享的
        }
    }

三.由构造方法引出动态扩容机制

1.AraayList 的Add()方法构成:

1.add(E e)
	public boolean add(E e) {
        ensureCapacityInternal(size + 1); //增加一个元素,先进行内部容量确定
        elementData[size++] = e;
        return true;
    }
2. ensureCapacityInternal(int minCapacity)方法:
  private void ensureCapacityInternal(int minCapacity) {
  		//calculateCapacity:获取当前所需最小容量
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
3.calculateCapacity(Object[] elementData, int minCapacity)方法:
   private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//这个个人存在疑问,就是True的情况应该不是发生在代码执行时
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }
4.private void ensureExplicitCapacity(int minCapacity):
  private void ensureExplicitCapacity(int minCapacity) {
        modCount++; //记录此List被操作了多少次,也就是能改变当前List的size操作发生了多少次

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

四.扩容算法具体操作grow(int minCapacity):

1.进行扩容操作:oldCapacity + (oldCapacity >> 1) ,
举例 :DEFAULTCAPACITY = 10 ,扩容操作为10+(10>>1)= 10 + 5 =15
>>带符号右移操作 用八位示例为: 0000 1010(10) >> 0000 0101(5)

2.进行OOM判断,当超出最大容量抛出OOMerror

3.进行扩容操作,就是建立一个新的数组,将原数组值复制,而具体的复制算法,在System包中的arrayCopy方法使用C++实现的本地方法。

  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);//最大容量,并且判断OOM
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);//数组复制的具体算法 在System包的arrayCopy方法
      
    }

疑问:(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) ,此情况未分析清楚,无论是外部调用哪种构造方法方式获取ArrayList实例后,通过Add都不触发,反射也不会触发;所以个人猜测在内存分配时使用,需要进一步学习。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值