简单说说ArrayList

ArrayList的源码实现

1. Arraylist 的相关属性

/**
 * 默认设置数组长度: 10
 * Default initial capacity.
 */
private static final int DEFAULT_CAPACITY = 10;

/**
 * 一个空的数组
 * Shared empty array instance used for empty instances.
 */
private static final Object[] EMPTY_ELEMENTDATA = {};

/**
 *  一个默认为空容量的数组(obj)
 * 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 = {};

/**
 * 集合中存储数据的数组对象,transient表示不可以序列化
 * 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

/**
 * 用来表示list的长度(list中元素的数量)
 * The size of the ArrayList (the number of elements it     contains).
 *
 * @serial
 */
private int size;

2. 构造方法

a.无参的构造方法
public ArrayList() {
	//直接将空数组赋值给用来存储元素的elementData数组(默认数组为{})
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
b.有参的构造方法
public ArrayList(int initialCapacity) {
  //如果传入的参数大于0,将传入的initialCapacity长度的数组赋值给		//elementData;传入参数为0数组赋值为空数组;否则抛出异常
    if (initialCapacity > 0) {
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}
c. 构造一个包含指定集合的元素列表
/**
* Collection<? extends E> c 的意思是
* Collection<? extends E>解释:
*		1.实现了Collection接口
*   2.类型一定是E的子类
*   符号解释: ?:通配符
*/
public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    if ((size = elementData.length) != 0) {
        // c.toArray 有可能不返回一个 Object 数组
        if (elementData.getClass() != Object[].class)
            //使用 Arrays.copy 方法拷创建一个 Object 数组
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        // replace with empty array.
        this.elementData = EMPTY_ELEMENTDATA;
    }
}
小结构造方法

调用有参构造方法时,如果给定初始容量为0,或者传入集合为空集合(不是null),那么,将空数组EMPTY_ELEMENTDATA赋给elementData,此时在添加第一位元素时,不会扩容为10。(具体add方法分析)

3.add()方法

1.模拟无参构造方法第一次add的情况
public boolean add(E e) {
  			// 确定容量,动态扩容 无参构造size为0
        ensureCapacityInternal(size + 1);
        // 将元素放入对应位置
  			elementData[size++] = e;
        return true;
}
private void ensureCapacityInternal(int minCapacity) { //minCapacity为size + 1=1
     //先分析calculateCapacity
  ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

private static int calculateCapacity(Object[] elementData, int minCapacity) {
  			//初始化数组容器为默认,第一次添加没有动态扩容为==
       if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        //所以第一次返回是10(取两者大值,DEFAULT_CAPACITY默认数组长度是10)  
         return Math.max(DEFAULT_CAPACITY, minCapacity);
       }
  		  //如果不是第一次或者无参构造的话那么在这里直接返回 数组长度+1(if不成立的话就是返回传入参数:minCapacity)
       return minCapacity;
}

回到上一个方法: ensureExplicitCapacity

//动态扩容方法
private void ensureExplicitCapacity(int minCapacity) {
    modCount++; //这个最后单独说 是一种快速失败抛出并发异常的机制
  
    // overflow-conscious code
  	// 如果传入的minCapacity大于原来数组的长度,执行grow方法进行扩容 
		// 第一次 10 > 0
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}
private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;   //原来数组的长度 0
       /**
       * 位运算:下面的意思是新数组长度为 10 + 10的2进制右移位运算 10 的二进制为1010 --> 0101				 *(4+1=5)newCapacity=15
       */
        int newCapacity = oldCapacity + (oldCapacity >> 1);  
        //如果newCapacity - minCapacity < 0 将newCapacity赋值为传入的minCapacity
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)//如果长度超过int的最大长度 2的32次方-1
          //newCapacity小于0抛出异常,如果大于MAX_ARRAY_SIZE属性的话(Integer.MAX_VALUE - 8),赋值为int类型的最大值(2的32次方),否则为MAX_ARRAY_SIZE
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
  			// 第一次就是走这里将原本为空的数组赋值为长度为10的数组,完成动态扩容
        elementData = Arrays.copyOf(elementData, newCapacity);
}

最后回到add方法

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
       //最后将元素放入指定位置
        elementData[size++] = e;
        return true;
}
2. 模拟第2次添加
public boolean add(E e) {
  			// size + 1 = 2
        ensureCapacityInternal(size + 1);
        // 将元素放入对应位置  size++使用后自增
  			elementData[size++] = e;
        return true;
}
private void ensureCapacityInternal(int minCapacity) { // 2
     //先分析calculateCapacity
  ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) { 
  			
       if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
         return Math.max(DEFAULT_CAPACITY, minCapacity);
       }
			//直接返回2
       return minCapacity;
}
//动态扩容方法
private void ensureExplicitCapacity(int minCapacity) {
    modCount++; 
   //2<10,不执行grow扩容方法直接回到add方法开始添加元素到data[1]位置
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}
3. 模拟第11次添加
public boolean add(E e) {   //{1,2,3,4,5,6,7,8,9,10} 11
  			//11
        ensureCapacityInternal(size + 1);
  			elementData[size++] = e;
        return true;
}
private void ensureCapacityInternal(int minCapacity) { //minCapacity为size + 1=1
     //先分析calculateCapacity
  ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) { // 11
  			//初始化数组容器为默认,第一次添加没有动态扩容为==
       if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        //所以第一次返回是10(取两者大值,DEFAULT_CAPACITY默认数组长度是10)  
         return Math.max(DEFAULT_CAPACITY, minCapacity);
       }
  		  //如果不是第一次或者无参构造的话那么在这里直接返回 数组长度+1(if不成立的话就是返回传入参数:minCapacity)
       return minCapacity;
}
//动态扩容方法
private void ensureExplicitCapacity(int minCapacity) {
    modCount++; 
  //11-10>0
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}
private void grow(int minCapacity) {
        
        int oldCapacity = elementData.length;   //10
 
        int newCapacity = oldCapacity + (oldCapacity >> 1);  //15
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
  //    给一个15的数组
        elementData = Arrays.copyOf(elementData, newCapacity);
} 
//回到add方法给新数组赋值

4.get()方法

public E get(int index) {
        //校验长度是否索引越界判断
        rangeCheck(index);
  			//直接返回对应数组位置的值
        return elementData(index);
    }
private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

5.set()方法

//校验,替换,返回旧值
public E set(int index, E element) {
        rangeCheck(index);

        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }

6.remove方法

//根据位置删除
public E remove(int index) {
    rangeCheck(index);
 
    modCount++;
    E oldValue = elementData(index);
 
    //numMoved等于数组元素-索引位置-1.如果numMoved等于0。说明删除的元素是最后一位,
    //然后跳过if语句。
    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    //原数组中最后一个元素删除,数组容量不变
    elementData[--size] = null; // clear to let GC do its work
 
    return oldValue;
}
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
src:源数组;
srcPos:源数组要复制的起始位置;
dest:目的数组;
destPos:目的数组放置的起始位置;
length:复制的长度.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值