Java List 链表使用及源码分析

继承关系

ArrayList

LinkedList

源码分析

由上图,可以看到 ArrayList 和 LinkedList 的继承关系。
两者都是继承自 AbstractList。那么我们就先分析AbstractList 以及它所继承的类和接口。

1、由最抽象的 Iterable 开始分析源码。

//实现这个接口,让目标对象类能支持for-each循环
public interface Iterable<T> {
   
    //返回迭代器对象
    Iterator<T> iterator();

    //默认方法,遍历符合action要求的元素
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }
    
    //默认方法:从当前可迭代类中返回个可拆分的迭代器 Spliterator
    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

具体迭代器用法参考:廖老师的使用Iterator教程

Iterable 接口有一个返回了 iterator 方法,以及两个Java8才开始支持的默认方法:forEach 和 spliterator
这个接口代码比较简单,主要是做迭代器相关的操作。

2、接下来分析 Collection 接口的源码

点击查看Collection代码
public interface Collection<E> extends Iterable<E> {
    // Query Operations

    int size();

    boolean isEmpty();

    boolean contains(Object o);

    Iterator<E> iterator();

    Object[] toArray();

    // Modification Operations

    boolean add(E e);

    boolean remove(Object o);


    // Bulk Operations

    boolean containsAll(Collection<?> c);

   
    boolean addAll(Collection<? extends E> c);

    boolean removeAll(Collection<?> c);

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

    boolean retainAll(Collection<?> c);

    void clear();


    // Comparison and hashing

   
    boolean equals(Object o);

    int hashCode();

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

源码的注释写得很清晰,Collection接口中的方法主要分为以下几类操作:

绝大部分方法,我们只看方法名就能够知道是干什么的。单独讲讲 retainAll 方法的作用与使用:

简单来说,retainAll 方法是用来取两个 Collection 交集的方法。这个方法会修改当前集合对象。

       ArrayList<String> stringList = new ArrayList<>();
        stringList.add("Hello");
        stringList.add("World");
        stringList.add("Java");

        ArrayList<String> parameterStrList = new ArrayList<>();
        parameterStrList.add("Python");
        parameterStrList.add("Java");
        parameterStrList.add("Hello");

        System.out.println("retain方法执行前:" + stringList);
        stringList.retainAll(parameterStrList);

        System.out.println("retain方法执行后:" + stringList);
        System.out.println("retain方法参数:" + parameterStrList);

//retain方法执行前:[Hello, World, Java]
//retain方法执行后:[Hello, Java]
//retain方法参数:[Python, Java, Hello]

3. List接口源码分析

public interface List<E> extends Collection<E> {
    // Query Operations
    
    int size();
    boolean isEmpty();
    boolean contains(Object o);
    Iterator<E> iterator();
    Object[] toArray();
    <T> T[] toArray(T[] a);


    // Modification Operations
    boolean add(E e);
    boolean remove(Object o);


    // Bulk Modification Operations
    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);
    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);
        }
    }

    void clear();


    // 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
    int indexOf(Object o);
    int lastIndexOf(Object o);


    // List Iterators
    ListIterator<E> listIterator();
    ListIterator<E> listIterator(int index);

    // View
    List<E> subList(int fromIndex, int toIndex);
    @Override
    default Spliterator<E> spliterator() {
        return Spliterators.spliterator(this, Spliterator.ORDERED);
    }
}

可以看到List接口中的方法要多了很多。同 Collection 一样,大部分方法一眼就能看出它的作用,只讲解部分特殊的方法。

List接口不光返回了 Iterator ,也返回特有的 ListIterator。有了这个迭代器,我们可以在任意方向(前、后)遍历List,在迭代过程中修改List,获取迭代器当前在List的位置。

相比于 Iterator 接口, ListIterator接口多了:向前方向的方法,如hasPrevious、previous,获取位置的方法:nextIndex、previousIndex 等等。具体可以查看源码学习了解。

posted @ 2021-11-26 22:31  onerepublic  阅读(167)  评论(0编辑  收藏  举报