Jdk源码——ArrayList解析

本文详述了ArrayList的继承结构,包括Serializable、RandomAccess、Cloneable、Iterable、Collection、List、AbstractCollection和AbstractList接口的解析。讨论了ArrayList的遍历方式、toArray()方法以及迭代删除问题,强调了在并发修改情况下正确删除元素的方法。
摘要由CSDN通过智能技术生成

前言

本文主要针对 JDK1.8 的 ArrayList 源码进行解析,主要看源码注释,代码说明了全部实现细节。

I. 继承结构

ArrayList 的继承结构如下图所示,下面我们进行一一解析。
ArrayList继承结构

Serializable

Serializable 接口是启用其序列化功能的接口,接口定义如下:

public interface Serializable {
   
}

实现 java.io.Serializable 接口的类是可序列化的,在序列化和反序列化过程中需要特殊处理的类必须使用下列准确签名来实现特殊方法:

private void writeObject(java.io.ObjectOutputStream out) throws IOException;
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;

ArrayList 由于内部数组具有冗余,所以通过这两种方法来进行去冗余序列化。

RandomAccess

RandomAccess 接口是标记接口,内容为空。该标记接口表示该集合支持随机访问,接口定义如下:

public interface RandomAccess {
   
}

ArrayList 实现 RandomAccess 接口,LinkedList 并没有实现 RandomAccess 接口,随机访问影响我们在遍历列表的时候是用下标的方式还是迭代器的方式,从性能上看 对于支持快速随机访问的集合,下标的方式更快,迭代器较慢;不支持快速随机访问的集合,迭代器更快,下标的方式很慢

那么如何判断一个集合是否支持随机访问呢?

通过 instanceof 判断集合是否实现了 RandomAccess 接口。

具体可参考:https://blog.csdn.net/weixin_39148512/article/details/79234817

Cloneable

Cloneable 接口也是一个标记接口,当然也就是空接口。

public interface Cloneable {
   
}

类只有实现这个接口,然后在类中重写 Object 中的 clone() 方法,这样对象实例调用 clone() 方法才能克隆成功,缺一不可。如果不实现这个接口,直接调用 clone() 方法则会抛出 CloneNotSupportedException 异常。

查看 Object 中定义的 clone() 方法:

protected native Object clone() throws CloneNotSupportedException;

该方法为 native 方法,本地方法会在其中判断是否实现 Cloneable 接口,同时==该方法默认是浅拷贝==。

关于浅拷贝、深拷贝的概念,可以参考:https://blog.csdn.net/xinghuo0007/article/details/78896726

Iterable

一个集类要表明自己支持迭代,能有使用 foreach 语句的特权,就必须实现 Iterable 接口,表明是可迭代的。实现Iterable接口,需为 foreach 语句提供一个迭代器 Iterator,迭代器通过 iterator() 方法返回。

public interface Iterable<T> {
   
    
    // 返回迭代器
    Iterator<T> iterator();

    // =======以下是JDK1.8之后加入的,为lambda表达式准备的方法=======
    default void forEach(Consumer<? super T> action) {
   
        Objects.requireNonNull(action);
        for (T t : this) {
   
            action.accept(t);
        }
    }

    default Spliterator<T> spliterator() {
   
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

迭代器 Iterator 也是一个接口,接口包含3个基本方法,jdk1.8之后又加入一个。

public interface Iterator<E> {
   

    boolean hasNext();

    E next();

    // 删除最近一次已经迭代出的元素
    default void remove() {
   
        throw new UnsupportedOperationException("remove");
    }

    // =======JDK1.8之后加入的,为lambda表达式准备的方法=======
    default void forEachRemaining(Consumer<? super E> action) {
   
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}
Collection

Collection 定义了一些集合的公共行为,源码如下:

public interface Collection<E> extends Iterable<E> {
   
    // Query Operations

    boolean isEmpty();

    boolean contains(Object o);

    Iterator<E> iterator();

    /**
     * 按序返回一个数组,数组包含集合中的元素。返回的泛型也丢失了
     * 返回的数组是安全的,即集合不存在指向数组的任何引用
     * 该方法充当集合到数组的转化桥梁
     */
    Object[] toArray();

    /**
     * 返回包含此collection中所有元素的数组
     * 返回数组的运行时类型是指定数组的运行时类型
     * 如果集合适合指定的数组,则返回其中
     * 否则,将使用指定数组的运行时类型和此集合的大小分配一个新数组
     */
    <T> T[] toArray(T[] a);

    // Modification Operations

    /**
     * 向集合中尝试添加元素,可能不让添加,具体看集合对元素要求
     */
    boolean add(E e);

    /**
     * 尝试删除一个元素
     */
    boolean remove(Object o);


    // Bulk Operations 块操作

    /**
     * 集合是否包含c中的所有元素
     */
    boolean containsAll(Collection<?> c);

    /**
     * 尝试添加c的所有元素
     */
    boolean addAll(Collection<? extends E> c);

    /**
     * 尝试删除c中含有的所有元素
     */
    boolean removeAll(Collection<?> c);

    // jdk1.8新方法
    default boolean removeIf(Predicate<? super E> filter) {
   
        Objects.requireNonNull(filter);
        boolean removed = false;
        final Iterator<E> each = iterator();
        while (each.hasNext()) {
   
            if (filter.test(each.next())) {
   
                each.remove();
                removed = true;
            }
        }
        return removed;
    }

    /**
     * 相当于求与c的交集
     */
    boolean retainAll(Collection<?> c);

    /**
     * 清空集合
     */
    void clear();


    // Comparison and hashing

    boolean equals(Object o);

    int hashCode();

    // jdk1.8新方法
    @Override
    default Spliterator<E> spliterator() {
   
        return Spliterators.spliterator(this, 0);
    }

    default Stream<E> stream() {
   
        return StreamSupport.stream(spliterator(), false);
    }

    default Stream<E> parallelStream() {
   
        return StreamSupport.stream(spliterator(), true);
    }
}

为何是实现 Iterable 这个接口而不直接实现 Iterator 接口?

实现 Iterable 这个接口 Collection 集合调用一次 iterator() 即可返回一个新的迭代器实例,迭代器的实现是依赖于游标的,如果 Collection 集合直接实现 Iterator 接口,相当于一个集合实例对应只有一个迭代器,那么集合的多个遍历者共用一个迭代器的游标会出问题。现在多个遍历者可以每个人自己调用 iterator() 返回专属的迭代器(专属的游标),不会冲突。

List

List 接口继承自 Collection 接口,额外定义了一些列表特有的行为,主要为了区分于 Set 等。

/**
 * 有序、允许重复的集合,用户可以通过下表进行访问元素
 * 
 * 允许插入多个null
 *
 * 迭代遍历List更倾向于用下标方式
 *
 * List提供了一个特殊的迭代器实现类ListIterator,额外允许插入替换和双向访问
 *
 * List接口还提供了搜索元素的方法,基于性能考虑,需要慎重使用
 * 大部分都是线性时间复杂度
 *
 * 虽然允许列表将自己包含为元素,但此时equals和hashCode方法将不再在这样的列表上很好地定义
 */

public interface List<E> extends Collection<E> {
   
    // Query Operations

    /**
     * 列表元素数目,不超过int最大值
     */
    int size();

	// 来自Collection
    boolean isEmpty();
    boolean contains(Object o);
    Iterator<E> iterator();
    Object[] toArray();
    <T> T[] toArray(T[] a);


    // Modification Operations

    // 来自Collection
    boolean add(E e);
    boolean remove(Object o);


    // Bulk Modification Operations

    // 来自Collection
    boolean containsAll(Collection<?> c);
    boolean addAll(Collection<? extends E> c);
    boolean addAll(int index, Collection<? extends E> c);
    boolean removeAll(Collection<?> c);
    boolean retainAll(Collection<?> c);
    void clear();

    
    default void replaceAll(UnaryOperator<E> operator) {
   
        Objects.requireNonNull(operator);
        final ListIterator<E> li = this.listIterator();
        while (li.hasNext()) {
   
            li.set(operator.apply(li.next()));
        }
    }

    @SuppressWarnings({
   "unchecked", "rawtypes"})
    default void sort(Comparator<? super E> c) {
   
        Object[] a = this.toArray();
        Arrays.sort(a, (Comparator) c);
        ListIterator<E> i = this.listIterator();
        for (Object e : a) {
   
            i.next();
            i.set((E) e);
        }
    }


    // Comparison and hashing

    boolean equals(Object o);
    int hashCode();


    // Positional Access Operations 指定位置访问操作:增删改查

    E get(int index);
    E set(int index, E element);
    void add(int index, E element);
    E remove(int index);


    // Search Operations

    /**
     * 返回第一个o出现位置
     */
    int indexOf(Object o);

    /**
     * 返回最后一个o出现位置
     */
    int lastIndexOf(Object o);


    // List Iterators

    /**
     * 返回java.util.ListIterator迭代器
     */
    ListIterator<E> listIterator();

    /**
     * 返回游标在指定位置的java.util.ListIterator迭代器
     */
    ListIterator<E> listIterator(int index);

    // View

    /**
     * 返回List指定范围的子列表
     */
    List<E> subList(int fromIndex, int toIndex);


    @Override
    default Spliterator<E> spliterator() {
   
        return Spliterators.spliterator(this, Spliterator.ORDERED);
    }
}
AbstractCollection

AbstractCollection 是实现了 Collection 接口的一个抽象类,主要是实现了部分方法,减少直接实现一个集合的难度,自定义一个集合仅仅需要实现 AbstractCollection 中的抽象方法即可,如果集合有自己特殊的行为,重写方法即可。源码如下,这些方法在 ArrayList 中都会出现,但实现方式肯定是有所改变的。

/**
 * Collection接口的一个抽象实现类
 * 如果实现一个不可修改的集合,子类还需要实现iterator()和size()方法
 * 如果实现一个可修改的,子类还需要实现add()方法以及能remove的iterator
 */

public abstract class AbstractCollection<E> implements Collection<E> {
   
    /**
     * 唯一的构造函数
     */
    protected AbstractCollection() {
   
    }

    // Query Operations

    public abstract Iterator<E> iterator();
    public abstract int size();

    // 主要是利用size()和迭代器来默认实现下列方法
    public boolean isEmpty() {
   
        return size() == 0;
    }

    public boolean contains(Object o) {
   
        Iterator<E> it = iterator();
        if (o==null) {
   
            while (it.hasNext())
                if (it.next()==null)
                    return true;
        } else {
   
            while (it.hasNext())
                if (o.equals(it.next()))
                    return true;
        }
        return false;
    }

    public Object[] toArray() {
   
        // Estimate size of array; be prepared to see more or fewer elements
        Object[] r = new Object[size()];
        Iterator<E> it = iterator();
        for (int i = 0; i < r.length; i++) {
   
            if (! it.hasNext()) // fewer elements than expected
                return Arrays.copyOf(r, i);
            r[i] = it.next();
        }
        return it.hasNext() ? finishToArray(r, it) : r;
    }

    public <T> T[] toArray(T[] a) {
   
        // Estimate size of array; be prepared to see more or fewer elements
        int size = size();
        T[] r = a.length >= size ? a :
                  (T[])java.lang.reflect.Array
                  .newInstance(a.getClass().getComponentType(), size);
        Iterator<E> it = iterator();

        for (int i = 0; i < r.length; i++) {
   
            if (! it.hasNext()) {
    // fewer elements than expected
                if (a == r) {
   
                    r[i] = null; // null-terminate
                } else if (a.length < i) {
   
                    return Arrays.copyOf(r, i);
                } else {
   
                    System.arraycopy(r, 0, a, 0, i);
                    if (a.length > i) {
   
                        a[i] = null;
                    }
                }
                return a;
            }
            r[i] = (T)it.next();
        }
        // more elements than expected
        return it.hasNext() ? finishToArray(r, it) : r;
    }

    /**
     * 集合最大容量限制
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    /**
     * Reallocates the array being used within toArray when the iterator
     * returned more elements than expected, and finishes filling it from
     * the iterator.
     *
     * @param r the array, replete with previously stored elements
     * @param it the in-progress iterator over this collection
     * @return array containing the elements in the given array, plus any
     *         further elements returned by the iterator, trimmed to size
     */
    @SuppressWarnings("unchecked")
    private static <T> T[] finishToArray(T[] r, Iterator<?> it) {
   
        int i = r.length;
        while (it.hasNext()) {
   
            int cap = r.length;
            if (i == cap) {
   
                int newCap = cap + (cap >> 1) + 1;
                // overflow-conscious code
                if (newCap - MAX_ARRAY_SIZE > 0)
                    newCap = hugeCapacity(cap + 1);
                r = Arrays.copyOf(r, newCap);
            }
            r[i++] = (T)it.next();
        }
        // trim if overallocated
        return (i == r.length) ? r : Arrays.copyOf(r, i);
    }

    private static int hugeCapacity(int minCapacity) {
   
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError
                ("Required array size too large");
        return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
    }

    // Modification Operations
    public boolean add(E e) {
   
        throw new UnsupportedOperationException();
    }

    public boolean remove(Object o) {
   
        Iterator<E> it = iterator();
        if (o==null) {
   
            while (it.hasNext()) {
   
                if (it.next()==null) {
   
                    it.remove();
                    return true;
                }
            }
        } else {
   
            while (it.hasNext()) {
   
                if (o.equals(it.next()))</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值