package org.wsc.coding.basic.list;
import java.util.Arrays;
import java.util.ConcurrentModificationException;
import java.util.NoSuchElementException;
/**
* ArrayList类
*
* @author c_malina007
* @param <E>
*/
public class ArrayList<E> implements List<E> {
/** 元素个数 */
private int size;
/** 默认容量 */
private static final int DEFAULT_CAPACITY = 10;
/** 默认最大容量 */
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/** 默认数组 */
private static final Object[] EMPTY_ELEMENTDATA = {};
/** 用于存放元素 */
private Object[] elementData;
/**
* 无参构造将使用默认数组
*/
public ArrayList() {
elementData = EMPTY_ELEMENTDATA;
}
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return size == 0;
}
// @Override
// public boolean contains(Object o) {
// // TODO Auto-generated method stub
// return false;
// }
@Override
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
int cursor; // 当前索引
int lastRet = -1;//
@Override
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
@Override
public E next() {
if (cursor > size) {
throw new NoSuchElementException();
}
Object[] elementData = ArrayList.this.elementData;
if (cursor >= elementData.length) {
throw new ConcurrentModificationException();
}
return (E) elementData[lastRet = cursor++];
}
@Override
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
size--;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
@SuppressWarnings("unchecked")
@Override
public E[] toArray() {
return (E[]) elementData;
}
@Override
public <T> T[] toArray(T[] a) {
return null;
}
@Override
public boolean add(E element) {
// 保证数组长度正确
ensureCapacityInternal(size + 1);
// 使用后缀自操作符
elementData[size++] = element;
return true;
}
@Override
public boolean add(int index, E element) {
rangeCheckForAdd(index);// 进行添加操作的索引范围检查
// 保证数组长度正确
ensureCapacityInternal(size + 1);
// 源数组中位置在 srcPos 到 srcPos+length-1 之间的组件被分别复制到目标数组中的 destPos 到
// destPos+length-1 位置
System.arraycopy(elementData, index, elementData, index + 1, size - index);
elementData[index] = element;
size++;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == EMPTY_ELEMENTDATA)
minCapacity = Math.max(minCapacity, DEFAULT_CAPACITY);
// 传入最小容量大于当前数组长度,则扩容
if (minCapacity > elementData.length)
grow(minCapacity);
}
/**
* 扩容
*
* @param minCapacity
*/
private void grow(int minCapacity) {
int oldCapacity = elementData.length;// 获取原数组长度
// 计算新容量
int newCapacity = oldCapacity + (oldCapacity >> 1);// 原容量+(原容量/2),使用位移符提高运行速度
newCapacity = newCapacity < minCapacity ? minCapacity : newCapacity;
if (newCapacity > MAX_ARRAY_SIZE)
newCapacity = hugeCapacity(newCapacity);
// 将原数组数据复制到一个长度为newCapacity的新数组中
elementData = Arrays.copyOf(elementData, newCapacity);
}
/**
* 传入容量是否大于最大容量常量,如大于最大容量,则返回int类型所能表示的最大值 ArrayList最大容量为int类型所能表示的最大值
*
* @param minCapacity
* @return
*/
private int hugeCapacity(int minCapacity) {
if (minCapacity < 0) {
throw new OutOfMemoryError("The index cannot be negative");
}
return minCapacity > MAX_ARRAY_SIZE ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}
@SuppressWarnings("unchecked")
@Override
public E get(int index) {
rangeCheck(index);// 进行索引的范围检查
return (E) elementData[index];
}
@SuppressWarnings("unchecked")
@Override
public E set(int index, E element) {
rangeCheck(index);// 进行索引的范围检查
// 取到指定索引元素,将新元素置入该索引位,并返回原元素
E oldValue = (E) elementData[index];
elementData[index] = element;
return oldValue;
}
@SuppressWarnings("unchecked")
@Override
public E remove(int index) {
rangeCheck(index);// 进行索引的范围检查
// 获取指定索引处元素
E rmValue = (E) elementData[index];
// 源数组中位置在 srcPos 到 srcPos+length-1 之间的组件被分别复制到目标数组中的 destPos 到
// destPos+length-1 位置
System.arraycopy(elementData, index + 1, elementData, index, size - (index - 1));
size--;
return rmValue;
}
// @Override
// public int indexOf(Object o) {
// // TODO Auto-generated method stub
// return 0;
// }
/**
* 添加时的索引范围检查
*
* @param index
*/
private void rangeCheckForAdd(int index) {
if (index > this.size || index < 0)// 添加可以往末位插入,所以这里索引等于元素个数也可以
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/**
* 索引范围检查
*
* @param index
*/
private void rangeCheck(int index) {
if (index < 0 || index >= this.size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/**
* 以字符串形式返回索引和元素个数信息
*
* @param index
* @return
*/
private String outOfBoundsMsg(int index) {
return "Index: " + index + ", Size: " + this.size;
}
}