ArrayList源码分析

package com.mybatis.controller;

import java.util.*;
import java.util.function.Consumer;

/**
 * @创建人 yfc
 * @创建时间 2019-09-19 14:00
 * @描述 ArrayList是线程不安全,ArrayList 动态数组实现,查询效率高
 */
public class YArrayList<E> extends AbstractList<E> {

	/**
	 * ArrayList的大小(它包含的元素数),知道ArrayList的实际元素大小。
	 */
	private int size;

	/**
	 * 默认初始容量
	 */
	private static final int DEFAULT_CAPACITY = 10;
	/**
	 * 用于空实例的共享空数组实例。
	 */
	private static final Object[] EMPTY_ELEMENTDATA = {};
	/**
	 * 存储ArrayList元素的数组缓冲区,ArrayList的容量是此数组缓冲区的长度
	 * 定义一个不允许序列化的数组
	 */
	transient Object[] elementData; // non-private to simplify nested class access
	/**
	 * 定义一个默认的空数组对象
	 */
	private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
	/**
	 * 要分配的数组的最大大小。某些虚拟机在数组中保留一些头字。
	 * 尝试分配较大的数组可能会导致OutOfMemory错误:请求的数组大小超过虚拟机限制
	 * 最大大小大约为21亿
	 */
	private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

	/**
	 * 默认构造函数
	 */
	public YArrayList() {
		this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
	}

	/**
	 * 将指定的元素追加到此列表的末尾
	 */
	public boolean add(E e) {
		//当前ArrayList的大小+1(将当前对象追加到ArrayList的后面)
		ensureCapacityInternal(size + 1);  // Increments modCount!!
		//size++:新增元素的位置 e:新增位置对应的元素
		/**
		 * 线程不安全,在多线程的时候无法保证新增的正确性
		 */
		elementData[size++] = e;
		return true;
	}

	//minCapacity:当前对象追加后的集合的大小
	private void ensureCapacityInternal(int minCapacity) {
		//判断当前ArrayList元素的数组缓冲区是否为空
		if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
			//当前集合大小和默认初始容量之间选出最大值
			minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
		}

		ensureExplicitCapacity(minCapacity);
	}


	private void ensureExplicitCapacity(int minCapacity) {
		//用来做快速失败
		modCount++;

		// 判断是否需要扩容,当前数组大小大于当前缓存区容量大小,则需要扩容
		if (minCapacity - elementData.length > 0)
			grow(minCapacity);
	}

	/**
	 * 增加容量以确保它至少可以容纳由最小容量参数指定的元素数。(扩容,ArrayList扩容为原先大小的1.5倍)
	 */
	private void grow(int minCapacity) {
		//老的数组容量
		int oldCapacity = elementData.length;
		//新的数组容量oldCapacity >> 1:缩短为原来的一半     =》新的扩容为原来的1.5倍
		int newCapacity = oldCapacity + (oldCapacity >> 1);
		//新容量如果小于实际需要的容量,则扩容大小为实际需要的容量
		if (newCapacity - minCapacity < 0)
			newCapacity = minCapacity;
		//新容量如果大于ArrayList最大容量
		if (newCapacity - MAX_ARRAY_SIZE > 0)
			newCapacity = hugeCapacity(minCapacity);
		// 传回的数组是扩容后的数据元素
		elementData = Arrays.copyOf(elementData, newCapacity);
	}

	private static int hugeCapacity(int minCapacity) {
		if (minCapacity < 0) // overflow
			throw new OutOfMemoryError();
		//如果实际容量大小大于ArrayList的最大容量,就赋值Integer的最大值,不然就设置ArrayList的最大容量值
		return (minCapacity > MAX_ARRAY_SIZE) ?
				Integer.MAX_VALUE :
				MAX_ARRAY_SIZE;
	}

	//根据下标获取对应的元素
	public E get(int index) {
		rangeCheck(index);
		return elementData(index);
	}

	//如果没有发生下标越界、根据索性位置定位到当前对象并返回
	E elementData(int index) {
		return (E) elementData[index];
	}
	/**
	 *检查给定索引是否在范围内。如果不是,则抛出适当的运行时异常。
	 * 此方法不检查索引是否为负:它总是在数组访问之前使用,如果索引为负,则数组访问将抛出ArrayIndexOutOfBoundsException。
	 */
	private void rangeCheck(int index) {
		if (index >= size)
			throw new IndexOutOfBoundsException("数组下标越界!");
	}

	public int size() {
		checkForComodification();
		return this.size;
	}
	private void checkForComodification() {
		if (YArrayList.this.modCount != this.modCount)
			throw new ConcurrentModificationException();
	}

	/**
	 * 删除此列表中指定位置的元素。将任何后续元素向左移动(从其索引中减去一个)。
	 * 删除的效率较低,每次删除之前需要移动复制数组
	 */
	public E remove(int index) {
		//检测下标是否越界
		rangeCheck(index);

		//快速失败
		modCount++;
		//返回当前下标对应的值
		E oldValue = elementData(index);

		//需要移动的数组下标:eg:实际大小4(a,b,c,d),要删除1(b)位置的元素,那么需要移动的位置应该是从2(c)开始,因为数组下标从0开始
		int numMoved = size - index - 1;
		if (numMoved > 0)
			//代码解释:原数组、从元数据的起始位置开始、目标数组、目标数组的起始位置,要copy的数组的长度,复制c,d放在目标数组,从1的位置开始
			System.arraycopy(elementData, index+1, elementData, index, numMoved);
		//设置elementData[3]为null,此时的elementData为[a,c,d]
		elementData[--size] = null; // clear to let GC do its work

		return oldValue;
	}

	public void clear() {
		modCount++;

		// 通过循环遍历,将每个元素的值设为空,并且将size的值设为0
		for (int i = 0; i < size; i++)
			elementData[i] = null;

		size = 0;
	}

	/**
	 * 以正确的顺序返回此列表中元素的迭代器。
	 */
	public Iterator<E> iterator() {
		return new Itr();
	}


	/**
	 * 内部类
	 *
	 * YArrayList<String > list=new YArrayList<>();
	 * 		list.add("a");
	 * 		Iterator iterator = list.iterator();
	 * 		int i=0;
	 * 		while(iterator.hasNext()){
	 * 			String str = (String) iterator.next();
	 * 			list.remove(i);
	 * 			i++;
	 *                }
	 * 上述代码运行报错,原因:modCount发生改变
	 * modcount 快速失败
	 */
	private class Itr implements Iterator<E> {

		int cursor;       // 要返回的下一个元素的索引
		int lastRet = -1; // 返回的最后一个元素的索引
		//expectedModCount的初值为modCount
		int expectedModCount = modCount;

		//hasNext的判断条件为cursor!=size,就是当前迭代的位置不是数组的最大容量值就返回true
		public boolean hasNext() {
			return cursor != size;
		}

		@SuppressWarnings("unchecked")
		public E next() {
			checkForComodification();
			int i = cursor;
			if (i >= size)
				throw new NoSuchElementException();
			Object[] elementData = YArrayList.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 {
				YArrayList.this.remove(lastRet);
				cursor = lastRet;
				lastRet = -1;
				expectedModCount = modCount;
			} catch (IndexOutOfBoundsException ex) {
				throw new ConcurrentModificationException();
			}
		}

		@Override
		@SuppressWarnings("unchecked")
		public void forEachRemaining(Consumer<? super E> consumer) {
			Objects.requireNonNull(consumer);
			final int size = YArrayList.this.size;
			int i = cursor;
			if (i >= size) {
				return;
			}
			final Object[] elementData = YArrayList.this.elementData;
			if (i >= elementData.length) {
				throw new ConcurrentModificationException();
			}
			while (i != size && modCount == expectedModCount) {
				consumer.accept((E) elementData[i++]);
			}
			// update once at end of iteration to reduce heap write traffic
			cursor = i;
			lastRet = i - 1;
			checkForComodification();
		}


		final void checkForComodification() {
			//检查modCount,expectedModCount是否一致,不一致抛出异常
			if (modCount != expectedModCount)
				throw new ConcurrentModificationException();
		}
	}

}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值