河北王校长源码之ArrayList

ArrayListy

类结构

  • 继承AbstractList
  • 实现List
    • list基本方法
  • 实现RandomAccess
    • 支持随机访问(下标)
    • for效率高于迭代器(对比LinkedList)
  • 实现Cloneable
    • 浅克隆
  • 实现Serializable
    • 序列化

成员变量

  • 默认容量
    • private static final int DEFAULT_CAPACITY = 10;
  • 空数组
    • private static final Object[] EMPTY_ELEMENTDATA = {};
  • 默认容量数组
    • private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
  • 元素数组
    • transient Object[] elementData;
      • 不进行数组序列化
      • 重写序列化方法,序列化时取出每个元素进行

方法

构造方法

    // 提前创建数组容量,不适用于小数组
	public ArrayList(int initialCapacity) {
        // 构造函数指定容量>0,进行指定容量赋值
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } 
        // 构造函数指定容量=0,使用空数组
        else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }
 	public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

添加方法

    public boolean add(E e) {
        ensureCapacityInternal(size + 1); 
        elementData[size++] = e;
        return true;
    }
	public void add(int index, E element) {
        // 越界检查
        rangeCheckForAdd(index);
        ensureCapacityInternal(size + 1);  
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

容量方法

	private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
	// 计算容量
 	private static int calculateCapacity(Object[] elementData, int minCapacity) {
        // 判断是否为默认容量
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            // 取扩容最小值和默认值较大者
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }
	// 判断容量
    private void ensureExplicitCapacity(int minCapacity) {
        // 快速失败计数
        modCount++;
        // 容量不足,扩容
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
	// 扩容
    private void grow(int minCapacity) {
        // 计算扩容
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        // 新容量不足,使用最小容量为新容量
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        // 新容量不安全,使用最大安全容量
        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();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

复制方法

    public static <T> T[] copyOf(T[] original, int newLength) {
        return (T[]) copyOf(original, newLength, original.getClass());
    }
    public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
        @SuppressWarnings("unchecked")
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

收缩方法

    public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size);
        }
    }

包含方法

    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }
    public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

克隆方法

    public Object clone() {
        try {
            ArrayList<?> v = (ArrayList<?>) super.clone();
            v.elementData = Arrays.copyOf(elementData, size);
            // 快速失败计数清零
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e);
        }
    }

转换数组方法

    public <T> T[] toArray(T[] a) {
        if (a.length < size)
            return (T[]) Arrays.copyOf(elementData, size, a.getClass());
        System.arraycopy(elementData, 0, a, 0, size);
        if (a.length > size)
            a[size] = null;
        return a;
    }

得到方法

  	public E get(int index) {
        // 越界检查
        rangeCheck(index);
        return elementData(index);
    }
    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

设置方法

    public E set(int index, E element) {
        // 越界检查
        rangeCheck(index); 
        E oldValue = elementData(index);
        elementData[index] = element;
        // 返回旧值
        return oldValue;
    }

移除方法

    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);
        // 置为null,开始gc工作
        elementData[--size] = null; 
        return oldValue;
    }  
    public boolean remove(Object o) {
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }
    private void fastRemove(int index) {
        modCount++;
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; 
    }

清理方法

    public void clear() {
        // 快速失败计数
        modCount++;
        // 置为null,开始gc工作
        for (int i = 0; i < size; i++)
            elementData[i] = null;
        size = 0;
    }

添加集合方法

	// 布尔类型表示是否添加成功,慎用,添加空数组返回false
	public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew); 
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }

    public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  
        int numMoved = size - index;
        if (numMoved > 0)
            System.arraycopy(elementData, index, elementData, index + numNew,
                             numMoved); 
        System.arraycopy(a, 0, elementData, index, numNew);
        size += numNew;
        return numNew != 0;
    }

范围移除方法

    // 包内访问权限和继承访问权限,左闭右开
	protected void removeRange(int fromIndex, int toIndex) {
        modCount++;
        int numMoved = size - toIndex;
        System.arraycopy(elementData, toIndex, elementData, fromIndex,
                         numMoved);
        int newSize = size - (toIndex-fromIndex);
        for (int i = newSize; i < size; i++) {
            elementData[i] = null;
        }
        size = newSize;
    }

添加越界判断方法

    private void rangeCheckForAdd(int index) {
        // 短路与,将高频率情况放置在前
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

移除集合方法

	// 移除ArrayList中与给定集合中元素相匹配的所有元素
	public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, false);
    }
	// 保留ArrayList中与给定集合中元素相匹配的所有元素
    public boolean retainAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, true);
    } 
	// 批量移除或保留与给定集合相匹配或不匹配的元素
	private boolean batchRemove(Collection<?> c, boolean complement) {
        final Object[] elementData = this.elementData;
        // 读取,写入指针
        int r = 0, w = 0;
        boolean modified = false;
        try {
            for (; r < size; r++)
                // 该读取位置元素不在需要被移除的数组中(不包含,需要保留),移动到写入指针,指针移动
                if (c.contains(elementData[r]) == complement)
                    elementData[w++] = elementData[r];
        } finally {
            // 读取指针未结束,仍然存在元素,将剩余元素直接复制,写入指针延长
            if (r != size) {
                System.arraycopy(elementData, r, elementData, w, size - r);
                w += size - r;
            }
            // 写入指针未结束,存在移除
            if (w != size) {
                for (int i = w; i < size; i++)
                    elementData[i] = null;
                // 快速失败计数
                modCount += size - w;
                size = w;
                modified = true;
            }
        }
        return modified;
    }

序列化方法

	// 节省空间,无需考虑null序列化
	private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException{
        // 快速失败计数局部化(本身不能被序列化,防止被修改)
        int expectedModCount = modCount;
        // 基本信息写入输出流
        s.defaultWriteObject();
        // 写入 ArrayList 的大小 size
        s.writeInt(size);
        // 序列化每个元素
        for (int i=0; i<size; i++) {
            s.writeObject(elementData[i]);
        }
        if (modCount != expectedModCount) {
            // 业务高于序列化
            throw new ConcurrentModificationException();
        }
    }
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        // 设置初始空数组
        elementData = EMPTY_ELEMENTDATA;
        // 恢复 ArrayList 的基本信息
        s.defaultReadObject();
        // 获取集合长度
        s.readInt(); 
        if (size > 0) {
            // 计算容量
            int capacity = calculateCapacity(elementData, size);
            // 检查数组的类型和容量的有效性
            SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);
            // 确保容量
            ensureCapacityInternal(size);
            Object[] a = elementData;
            for (int i=0; i<size; i++) {
                // 反序列化每个元素
                a[i] = s.readObject();
            }
        }
    }

特殊ArrayList

	// 元素必须固定,仅仅支持修改的场景(get(),set())
	List<Object> objects = Arrays.asList();
	// 返回空List场景(不支持任何操作)
	List<Object> objects = Collections.emptyList();

槽点

  • 继承AbstractList情况下,依旧实现List接口
  • addAll()方法在提供集合为空时,返回false
  • removeAll()retainAll()方法仅仅用Objects.requireNonNull(c)过滤null值,对空数组没有处理
  • batchRemove()内部使用try catch并未捕获异常
  • Collections.emptyList()提供的空List不支持操作,但实现了RandomAccess

优点

  • E set(int index, E element)E remove(int index)返回旧值
  • 越界判断,短路与,将高频率情况放置在前
  • for循环遍历,提高性能
  • 重写序列化方法,不序列化整个数组,取出元素依次序列化
posted @ 2024-03-14 20:10  Faetbwac  阅读(4)  评论(0编辑  收藏  举报