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();
}
}
}