Java基础 - 集合 - 源码 - ArrayList


注:本文档基于  JDK-version 1.8.0_102  编写

实现/继承关系

在这里插入图片描述
RandomAccess  标记型接口,表明支持快速随机访问。具体内容可查看 Collections类中的 binarySearch(..)方法
Serializable  启用序列化支持
Cloneable     标记型接口,表明该对象可以被克隆,使用Object.clone()方法

成员变量

private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData;
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private int size;

DEFAULT_CAPACITY
初始默认容量

EMPTY_ELEMENTDATA
共享空数组,无参构造时使用

DEFAULTCAPACITY_EMPTY_ELEMENTDATA
默认大小的共享空数组

elementData
数据存储缓冲区数组,ArrayList的所有元素都存储在该数组中

MAX_ARRAY_SIZE
可存储元素数量的最大值,尝试保存元素数量超过该值将导致 OutOfMemoryError - 内存溢出
一般情况下,由于JVM分配的内存较小,实际可用最大容量远远低于这个值

size
实际存储的元素的数量

构造方法

ArrayList()
空参构造方法,集合元素数组 elementData 初始化为空数组

ArrayList(Collection<? extends E> c)
以原集合构造新集合对象,原集合为空,集合元素数组 elementData 初始化为空数组;否则直接将原集合中的元素按原顺序保存到新集合的元素数组 elementData

ArrayList(int initialCapacity)
指定初始化容量构造集合的对象

源码
/**
 * 空参构造
 */
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;  //保存集合元素的数组初始化为空数组
}

/**
 * 参数为指定Collection的构造方法
 */
public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    if ((size = elementData.length) != 0) {
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        //由于 toArray()方法存在可能返回的不是Object[]的bug,需要对非Object[]的elementData做一次类型转换
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        this.elementData = EMPTY_ELEMENTDATA;
    }
}

/**
 * 指定初始容量的构造方法
 */
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);
    }
}
使用示例
public static void main(String[] args) {
	//空参构造
	List<String> stringList = new ArrayList<>();
	
	//参数为Collection的构造方法
	//Meat extends Food
	List<Meat> meatList = new ArrayList<>();
    ArrayList<Food> meatFoodList = new ArrayList<>(meatList);
    ArrayList<Food> foodList = new ArrayList<>(meatFoodList);

	//指定初始化容量的构造方法
	List<Meat> meatList = new ArrayList<>(20);
}


普通方法

add

add(E e) & add(int index, E element)

//源码
/**
 * 集合尾部新增一个新元素
 */
public boolean add(E e) {
	//对modCount计数器的计数操作
	//确定当前容量是否可以支撑新增一个元素的操作,不足以支撑便进行扩容
    ensureCapacityInternal(size + 1);
    elementData[size++] = e;
    return true;
}

/** 	
 * 在指定位置插入一个新元素
 */
public void add(int index, E element) {
	//检查是否索引越界,该方法会抛出 IndexOutOfBoundsException 异常
    rangeCheckForAdd(index);
    //对modCount计数器的计数操作
	//确定当前容量是否可以支撑新增一个元素的操作,不足以支撑便进行扩容
    ensureCapacityInternal(size + 1);
    //将新元素插入到指定位置(index), 原集合该位置后面的元素后挪
    System.arraycopy(elementData, index, elementData, index + 1,
                     size - index);
    elementData[index] = element;
    size++;
}
addAll

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

//源码
/**
 * 方法调用对象的尾部新增 参数中的集合中的元素
 */
public boolean addAll(Collection<? extends E> c) {
    Object[] a = c.toArray();
    int numNew = a.length;
    //对modCount计数器的计数累加操作
	//确定当前容量是否可以支撑吞并集合的操作,不足以支撑便进行扩容
    ensureCapacityInternal(size + numNew);
    System.arraycopy(a, 0, elementData, size, numNew);
    size += numNew;
    return numNew != 0;
}

/**
 * 方法调用对象的指定位置插入 参数中的集合中的元素,原集合指定位置之后的元素后挪
 */
public boolean addAll(int index, Collection<? extends E> c) {
	//检查是否索引越界,该方法会抛出 IndexOutOfBoundsException 异常
    rangeCheckForAdd(index);
    Object[] a = c.toArray();
    int numNew = a.length;
    //对modCount计数器的计数累加操作
	//确定当前容量是否可以支撑吞并集合的操作,不足以支撑便进行扩容
    ensureCapacityInternal(size + numNew);
    int numMoved = size - index;
    //扩容后,size >= index 恒成立
    if (numMoved > 0)
    	//中间插入操作
        System.arraycopy(elementData, index, elementData, index + numNew, numMoved);
    //尾部新增操作
    System.arraycopy(a, 0, elementData, index, numNew);
    size += numNew;
    return numNew != 0;
}
remove

remove(int index) & remove(Object o)

//源码
/**
 * 删除指定索引位置的元素
 */
public E remove(int index) {
	//检查是否索引越界
    rangeCheck(index);
    modCount++;
    //获取指定索引位置的元素值
    E oldValue = elementData(index);
    int numMoved = size - index - 1;
    if (numMoved > 0)
    	//索引位置后的元素前移
        System.arraycopy(elementData, index+1, elementData, index, numMoved);
    // clear to let GC do its work
    elementData[--size] = null;
    return oldValue;
}

/**
 * 根据元素匹配删除
 * 方法内部调用的 fastRemove(index)方法 与 remove(int index) 相比较, 
 * 不再检查索引越界, 不需要获取已删除元素, 其他再无区别
 */
 public boolean remove(Object o) {
    if (o == null) {
        for (int index = 0; index < size; index++)
            if (elementData[index] == null) {
                fastRemove(index);
                return true;
            }
    } else {
        for (int index = 0; index < size; index++)
            if (o.equals(elementData[index])) {
                fastRemove(index);
                return true;
            }
    }
    return false;
}
removeAll

removeAll(Collection<?> c)
性能较差,数据量较大的情况下不建议使用

public boolean removeAll(Collection<?> c) {
    Objects.requireNonNull(c);
    return batchRemove(c, false);
}
clone

该方法的拷贝是浅拷贝,即不会拷贝集合中的元素

/**
 * Returns a shallow copy of this <tt>ArrayList</tt> instance.
 * 浅拷贝
 * 要想实现深拷贝,需要重写 Object.clone() 方法
 */
public Object clone() {
    try {
        ArrayList<?> v = (ArrayList<?>) super.clone();
        v.elementData = Arrays.copyOf(elementData, size);
        v.modCount = 0;
        return v;
    } catch (CloneNotSupportedException e) {
        // this shouldn't happen, since we are Cloneable
        throw new InternalError(e);
    }
}

fastRemove(int index)
remove(int index) 相比没有索引越界的检查, 没有已删除元素的获取和返回, 其他再无区别

private void fastRemove(int index) {
	//
    modCount++;
    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
}

batchRemove(Collection<?> c, boolean complement)
该方法共有两处调用: removeAll(..) retainAll(..)

private boolean batchRemove(Collection<?> c, boolean complement) {
    final Object[] elementData = this.elementData;
    int r = 0, w = 0;
    boolean modified = false;
    try {
    	//遍历元素数组 elementData
    	// w <= r
    	//结果是,有 w 个符合判断条件的元素,那么元素数组 0 ~ (w-1) 的索引位置放置的便是这些元素
    	//在removeAll(..)方法中,由于complement 为 false, 故 0 ~ (w-1) 索引位置的便是要删除的元素
    	//在retainAll(..)方法中,由于complement 为 true, 故 0 ~ (w-1) 索引位置的便是两个集合共有的元素
        for (; r < size; r++)
            if (c.contains(elementData[r]) == complement)
                elementData[w++] = elementData[r];
    } finally {
        // 当 c.contains() 抛出异常的时候 r != size
        if (r != size) {
        	//将抛出异常的元素索引位置后面的元素前移到 w 索引位置之后
            System.arraycopy(elementData, r, elementData, w, size - r);
            w += size - r;
        }
        //removeAll(..), 当删除的集合与当前集合中没有任何交集时,w == size, modified == false
        //retainAll(..), 当查询的集合与当前集合元素一致时,w == size, modified == false
        //注: retainAll(..), 当查询的集合与当前集合元素一致时返回的是false, 只有是包含且元素不一致时才会返回true
        //这两种情况都不需要再做处理,return true 即可
        if (w != size) {
            for (int i = w; i < size; i++) {
            	//将所有不符合条件的元素全部置为null
				elementData[i] = null;
			} 
            modCount += size - w;
            size = w;
            modified = true;
        }
    }
    return modified;
}

fastRemove(int index)

private void fastRemove(int index) {
    modCount++;
    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
}

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++;   //计数器,来自于父类 AbstractList 的成员属性
    if (minCapacity - elementData.length > 0)
    	//现有 elementData 的容量不足,扩容
        grow(minCapacity);
}

ensureCapacity(int minCapacity)

public void ensureCapacity(int minCapacity) {
    int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
        // any size if not default element table
        ? 0
        // larger than default for default empty table. It's already
        // supposed to be at default size.
        : DEFAULT_CAPACITY;
    if (minCapacity > minExpand) {
        ensureExplicitCapacity(minCapacity);
    }
}

grow(int minCapacity)

/**
 * 扩容方法
 */
private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length; 
    int newCapacity = oldCapacity + (oldCapacity >> 1);   //原容量加上原容量的一半 即扩容1.5倍
    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);
}

hugeCapacity(int minCapacity)

private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0)
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}
未完待续
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值