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 等等。具体可以查看源码学习了解。