List集合解析
1. 容器整体框架图
1.1 List集合
List集合的特点:有序,可重复
- 有序:List中的每个元素都有索引标记,可以根据元素的索引标记访问元素
- 可重复:List中允许放入重复的元素
List接口常用的三个实现类:ArrayList, LinkedList , Vector
- ArrayList:底层用数组实现。特点:查询效率高,增删效率低,线程不安全。可以动态增长和缩减的一个索引序列。
- LinkedList:底层用双向链表实现。特点:查询效率低,增删效率高,线程不安全。可以在任何位置高效插入和删除的一个有序序列。
- Vector:底层用数组实现。特点:线程安全,效率低。
1.1.1 ArrayList
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
- 实现了RandomAccess接口,支持快速随机访问。因为ArrayList底层用数组实现,所以可以快速随机访问其中的元素。实现了RandomAccess接口的类用for循环的方式获取数据要优于用迭代器获取数据。
As a rule of thumb,this loop:
* <pre>
* for (int i=0, n=list.size(); i < n; i++)
* list.get(i);
* </pre>
runs faster than this loop
<pre>
* for (Iterator i=list.iterator(); i.hasNext(); )
* i.next();
* </pre>
- 实现了Cloneable接口。在类中重写Object中的clone()方法,创建并返回此实例的副本。如果没有实现该接口,则会抛出 CloneNotSupportedException 异常。
重写clone()方法的原则:
(1) x.clone != x (true)
(2)x.clone().getClass()==x.getClass() (true)
(3)x.clone().equals(x) (true)
protected native Object clone() throws CloneNotSupportedException;
- 实现了 Serializable 接口。(官方文档的解释)
没有实现此接口的类不会对其状态进行任何序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。
Classes that do not implement this interface will not have any of their state serialized or deserialized.
All subtypes of a serializable class are themselves serializable. The serialization
interface has no methods or fields and serves only to identify the semantics of being serializable.
(1)什么情况需要序列化(看了GNG博主给出的解释,写的很通俗易懂,很容易理解。)
序列化的定义:把原本在内存中的对象状态变成可存储或传输的过程称之为序列化
* 当你想把的内存中的对象状态保存到一个文件中或者数据库中,以便可以在以后重新创建精确的副本;
* 当你想用套接字在网络上传送对象的时候(从一个应用程序域发送到另一个应用程序域中);
* 当你想通过RMI传输对象的时候;
1.1.1.1 ArrayList的属性
// 默认的初始容量
private static final int DEFAULT_CAPACITY = 10;
// 空的数组
private static final Object[] EMPTY_ELEMENTDATA = {};
// 默认容量的空数组。(官方文档有这么一句话)
// We distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when first
// element is added.(与EMPTY_ELEMENTDATA的区别:当第一个元素被加入进来的时候它知道如何扩张)
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// 存储ArrayList的元素的数组缓冲区。添加第一个元素时,任何具有elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA 的空ArrayList都将扩展为DEFAULT_CAPACITY。
transient Object[] elementData; // non-private to simplify nested class access
// ArrayList的大小(它包含的元素数)
private int size;
1.1.1.2 ArrayList的构造函数
- 无参构造函数
// 直接将DEFAULTCAPACITY_EMPTY_ELEMENTDATA赋值给elementData
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
- 带 int 的构造函数
// 首先判断initialCapacity是否为0,如果是0,则将EMPTY_ELEMENTDATA赋值给elementData,如果大于0,就将elementData初始化为一个容量为initialCapacity的对象数组。如果小于0,抛出异常。
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
- 带 Collection 形参的构造函数
首先调用Collection的 toArray()方法,将结果赋值给elementData。如果elementData的长度为0,则将EMPTY_ELEMENTDATA赋值给elementData。如果不为0,则进行判断,c.toArray()不返回Object[],所以有 if (elementData.getClass() != Object[].class)的判断,如果if成立,进行数组拷贝。
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// defend against c.toArray (incorrectly) not returning Object[]
// (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
1.1.2 LinkedList
- LinkedList是一个继承于 AbstractSequentialList 的双向链表,可以被当作堆栈、队列或双端队列进行操作。
- LinkedList实现Deque接口,能够将LInkedList当做双端队列使用。(双端队列允许在头部和尾部都高效的添加或删除元素,不支持在队列中间添加元素。)
- LinkedList实现List接口,能对它进行队列操作。
- LinkedList实现了Cloneable接口。(和ArrayList一样)
- LinkedList实现了Serializable接口。(和ArrayList一样)
1.1.2.1 LinkedList的属性
// 链表节点个数
transient int size = 0;
// 首节点
transient Node<E> first;
// 尾结点
transient Node<E> last;
1.1.2.2 LinkedList的构造函数
- 无参构造函数
// Constructs an empty list.(创建一个空的列表)
public LinkedList() {
}
- 带Collection的构造函数
//Constructs a list containing the elements of the specified collection, in the order they
//are returned by the collection's iterator.(构造一个包含指定集合元素的列表,其顺序由集合的迭代器返回)
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}