全文使用JDK11
本篇目录
-
List接口的继承关系
-
ArrayList继承关系
-
ArrayList底层数据结构
-
LinkedList继承关系
-
LinkedList底层数据结构
-
Vector集合
可以看到有74个不同的类和接口实现了List
这个接口,如果每一个都要学习的话,会很乏力。
更好的方法是学习我们常用的,以后有更多的时间再去慢慢拓展。
List
接口的继承关系
由它的继承关系可以看到List
接口继承至Collection
接口,所以Collection
中有的方法,List
也继承过来了。
ArrayList
ArrayList
继承关系
毋庸置疑ArrayList
集合是我们最常使用的集合之一,是List
接口的一个实现类。
Cloneable
是一个标记接口,只有实现这个接口后,然后在类中重写clone
方法,然后通过类调用clone
方法才能克隆成功,如果不实现这个接口,则会抛出CloneNotSupportedException
(克隆不被支持)异常。
AbstractList
是一个抽象类,它也实现了List
接口。那为什么ArrayList
继承它,而不是直接去实现List
接口呢?这是因为List
的实现类太多了,为了减少这些类的重复代码,所以将它们写成一个抽象类。各位在开发过程中也可以用一下这个思想。
RandomAccess
也是一个标记接口,只有实现这个接口后,就能支持快速随机访问。往上追溯,可以在Collections
接口中的binarySearch()
方法中会判断当前的List
是否实现了RandomAccess
接口,然后再决定使用for循环
的还是使用迭代器
的形式遍历当前List
。
Serializable
也是一个标记接口,只有实现了这个接口后,这个类才能进行序列化。
ArrayList
底层数据结构
transient Object[] elementData;
从它的源码中可以看到底层是Object[]
,所以它可以存储几乎所有类型的数据。transient
关键字的作用是在序列化这个对象时,这个属性不会被序列化。
如果对ArrayList
感兴趣可以查看我另一篇对ArrayList
的详解,这篇文章的重心在介绍List
集合。
LinkedList
LinkedList
继承关系
Cloneable
和Serializable
上面介绍ArrayList
的时候说过了,这里就不提了。
AbstractSequentialList
抽象类继承至AbstractList
抽象类,而在上面有介绍后者,它俩的区别在前者只支持按次序访问,后者支持随机访问。这就是为什么LinkedList
集合没有实现RandomAccess
接口,因为它不支持随机访问。
Deque
接口定义了一个双端队列,它提供了一系列针对队列首尾元素的操作方法。而LinkedList
实现了该接口,意味着它可以做为一个双端队列来使用。
LinkedList
底层数据结构
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
LinkedList
本质上是一个双向链表,item
存储着本身的元素,next
指向下一个Node
,prev
指向上一个Node
。如下图:
Vector
可以从Vector
的继承关系中看出,它与ArrayList
应该比较相似。
Vector
和ArrayList
的底层数据结构、初始容量、扩容方式等都差不多。
不同的地方是Vector
相对来说是线程安全的,因为它的大多方法都使用synchronized
关键字,如果开发者对线程安全有更高的要求,推荐使用Vector
。
对于Vector
的详解,后面我会专门写一篇来介绍。