/** 考虑到Vector和ArrayList没有什么本质的区别,除了Vector可以指定扩容的大小和默认的两倍扩容策略和各种同步的方法外,基本的操作没什么质的不同,因此就不讨论Vector了*/
package test; import java.util.*; /** * Created by wenge on 2018/6/11. */ public class LArrayList<E> { transient Object[] elementData; private int size; private static final int DEFAULT_SIZE = 10; private static final Object[] EMPTY_ELEMENT = {}; private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; /** * 常规的初始化列表,其elementData为DEFAULTCAPACITY_EMPTY_ELEMENTDATA */ public LArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } /** * 根据初始化容量初始化列表 * * @param initialCapacity 初始化容量,要考虑鲁棒性 */ public LArrayList(int initialCapacity) { //如果initialSize > 0才可以安全初始化 if (initialCapacity > 0) { elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { elementData = EMPTY_ELEMENT; //如果初始容量为0,那么就将elementData初始化为空 } else { throw new IllegalArgumentException("Illegal Capacity : " + initialCapacity); } } /** * 根据集合来初始化 * <p> * 这里有一个bug,就是将集合元素赋值可能会有一点小问题 * 不是所有的Collection的toArray方法都能返回真正意义上的Object[] * 有些仅仅返回的是这种类型的引用,但是实际上里面的元素类型是具体的。 * 如:<code>Arrays.asList()</code>返回的Arrays$ArrayList的toArray里面的元素是具体类型 * objs.getClass()可能不是Object[].class * 而:ArrayList的toArray则返回的是真正意义上的Object[]数组 * * @param c 集合 */ public LArrayList(Collection<? extends E> c) { elementData = c.toArray(); //先把集合转换成为数组,但是有可能转换成为的数组不能存放Object类型 if ((size = elementData.length) != 0) { if (elementData.getClass() != Object[].class) { elementData = Arrays.copyOf(elementData, size, Object[].class); } } else { elementData = EMPTY_ELEMENT; } } /** * 当你想添加一个元素的时候,首先要看容量是否还足够 * 如果list刚刚创建,则将最小需要的容量改为10 * 根据最小需要的容量去看是否要扩容 * 如果当前容量足够,则不需要扩容 * 否则需要扩容,扩容的策略是将elementData的容量定位原先的1.5倍 * 如果1.5倍的容量还是不够,那么就扩容成为最小需要的容量 * 如果新的容量溢出了,则要考虑创建一个合适的容量,如果最少需要的容量超出了Integer的最大值 * 则抛出异常,否则如果需要的容量>数组的最大容量,那么就用Integer的最大值,否则就用最大数组的容量 * * @param e 需要添加的元素 * @return */ public boolean add(E e) { ensureCapacityInternal(size + 1); //看是否要扩容 elementData[size++] = e; return true; } private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //说明这个list才刚刚创建 minCapacity = Math.max(minCapacity, DEFAULT_SIZE); //则想将容量最少扩展为10 } ensureExplicitCapacity(minCapacity); //根据最少需要的容量去扩容 } private void ensureExplicitCapacity(int minCapacity) { if (minCapacity - elementData.length > 0) //容量不够就扩容 grow(minCapacity); } private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; private void grow(int minCapacity) { int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); //默认扩容1.5倍 if (newCapacity - minCapacity < 0) //1.5倍还不够的化就用minCapacity newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) //容量超过最大容量 newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData, newCapacity); } private int hugeCapacity(int minCapacity) { if (minCapacity < 0) //也就是说超出了int的取值范围 throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; } public E remove(int index) { rangeCheck(index); E oldEle = (E) elementData[index]; int numToMove = size - index - 1; if (numToMove > 0) { System.arraycopy(elementData, index + 1, elementData, index, numToMove); } elementData[--size] = null; //垃圾回收 return oldEle; } private void rangeCheck(int index) { //这里之所不考虑负数是因为数组的索引不能为负数,否则会抛出异常 if (index > size - 1) throw new IndexOutOfBoundsException("Index : " + index + ", Size : " + size); } public Object[] toArray() { return Arrays.copyOf(elementData, size); } public int size() { return size; } public boolean isEmpty() { return size == 0; } public boolean contains(Object o) { //contains基于迭代器 Iterator it = Arrays.asList(toArray()).iterator(); if (o == null) { while (it.hasNext()) if (null == it.next()) return true; } else { while (it.hasNext()) if (o.equals(it.next())) return true; } return false; } /** * 移除底部采用的是快慢指针,用不存在的元素替换存在的元素 * * @param c 移除的集合 * @return */ public boolean removeAll(Collection<E> c) { if (c == null) throw new IllegalArgumentException("参数不能为空"); return batchRemove(c, false); } private boolean batchRemove(Collection<E> c, boolean complete) { //批量删除基于双指针压缩 final Object[] elementData = this.elementData; int fast, slow; //w为慢指针,r为快指针 for (slow = 0, fast = 0; fast < size; fast++) { if (c.contains(elementData[fast]) == complete) { elementData[slow++] = elementData[fast]; } } for (int i = slow; i < size; i++) { elementData[i] = null; //help gc } size = slow; this.elementData = Arrays.copyOf(this.elementData, size); return true; } public String toString() { if (size == 0) { return "[]"; } StringBuilder sb = new StringBuilder("["); for (int i = 0; i < size; i++) { sb.append(elementData[i] + ", "); } String s = sb.substring(0, sb.length() - 2); sb = new StringBuilder(s); sb.append("]"); return sb.toString(); } /** * 标准迭代器,list还有一个内部实现的listIterator,可以查找前后元素,并且可以添加元素 */ private class Itr implements Iterator<E> { private int cursor; private int lastReturn = -1; //表示最后返回的一个元素的索引,用于恢复删除 @Override public boolean hasNext() { return cursor != size; } @Override public E next() { //next之后,游标指向下一个 lastReturn = cursor; cursor = cursor + 1; return (E) elementData[lastReturn]; //返回当前元素 } @Override public void remove() { //移除元素的时候要把游标归位,也就是归位到上一次返回元素的下标 LArrayList.this.remove(lastReturn); cursor = lastReturn; lastReturn = -1; } } public Iterator<E> iterate() { return new Itr(); } public void clear() { // help gc for(int i = 0; i < size; i++) { elementData[i] = null; } size = 0; } }