Java源码学习--01--ArrayList

ArrayList

  1. 概览
    ArrayList内部是数组实现,所以支持快速随机访问,同时,RandomAccess接口也标识着该类支持快速随机访问。
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
  1. 重要属性
//1. 默认大小为10
private static final int DEFAULT_CAPACITY = 10;

//初始化的空的数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

//内部的存储结构
transient Object[] elementData; // non-private to simplify nested class access

//ArrayList存储元素的个数
private int size;

//AbstractList中的关键属性:容器增加元素,删除元素 发生变化  都会增加1
//错误机制:用来判断,在操作过程中是否被其他操作,如果操作了,直接报错
protected transient int modCount = 0;

//ArrayList的最大容量
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

操作

1. 新增
  • add方法
public boolean add(E e) {
	//判断容器是否扩容,如果需要进行扩容
	ensureCapacityInternal(size + 1);  // Increments modCount!!
	elementData[size++] = e;
	return true;
}
private void ensureExplicitCapacity(int minCapacity) {
	modCount++;

	// overflow-conscious code
	if (minCapacity - elementData.length > 0)
		//扩容
		grow(minCapacity);
}
2. 扩容
  • 步骤
    1. 获取老的容量
    2. 计算新的容量:新的容量为老容器的1.5倍
    3. 设定的容量比新的容量大,使用设定的容量为新的容量
    4. 如果新的容量比最大的容量都大,使用最大容量(说明ArrayList的容量是有上限的)
  • grow
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);
	
	//底层调用的是Arrays的copyOf-》System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));
	elementData = Arrays.copyOf(elementData, newCapacity);
}
3. 删除
  • 返回删除的元素
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);
	elementData[--size] = null; // clear to let GC do its work

	return oldValue;
}
4. 跟新
  • 按照索引来更新值
public E set(int index, E element) {
	rangeCheck(index);

	E oldValue = elementData(index);
	elementData[index] = element;
	return oldValue;
}
5. 遍历,容器中使用了迭代器模式,使用Iterator可以进行遍历
  • 内置迭代器
public Iterator<E> iterator() {
	return new Itr();
}

/**
 * An optimized version of AbstractList.Itr
 */
private class Itr implements Iterator<E> {

	//表示下一个元素的索引
	int cursor;       // index of next element to return
	
	//表示上次返回的索引值,如果是-1表示,上次操作是删除,或者是刚开始操作
	int lastRet = -1; // index of last element returned; -1 if no such
	
	//记录一开始的修改记录,用于在遍历的过程中,如果外部调用了非迭代器的修改Array元素的方法,就会执行报错机制
	int expectedModCount = modCount;

	Itr() {}

	public boolean hasNext() {
		return cursor != size;
	}

	@SuppressWarnings("unchecked")
	public E next() {
		//验证报错机制
		checkForComodification();
		int i = cursor;
		if (i >= size)
			throw new NoSuchElementException();
		Object[] elementData = ArrayList.this.elementData;
		if (i >= elementData.length)
			throw new ConcurrentModificationException();
		cursor = i + 1;
		return (E) elementData[lastRet = i];
	}

	public void remove() {
		if (lastRet < 0)
			throw new IllegalStateException();
		checkForComodification();

		try {
			ArrayList.this.remove(lastRet);
			cursor = lastRet;
			
			lastRet = -1;
			
			//使用迭代器可以在遍历的同时,删除元素
			expectedModCount = modCount;
		} catch (IndexOutOfBoundsException ex) {
			throw new ConcurrentModificationException();
		}
	}

	//校验是否被更改过
	final void checkForComodification() {
		if (modCount != expectedModCount)
			throw new ConcurrentModificationException();
	}
}

可取之处

  • 使用迭代器模式,让外部可以以统一的方式进行遍历
  • 报错机制的使用,是通过两个字段来进行比较,如果不一致则fast-fail
  • 数组存在最大值
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值