一、LinkedList定义
LinkedList是一个用链表实现的集合,元素有序且可以重复。
和ArrayList集合一样,LinkedList集合也实现了Cloneable接口和Serializable接口
- Cloneable接口:支持Oject.clone()克隆
- Serializable接口:支持序列化
- List接口:定义了一套List集合类型的方法规范
注意:相对于ArrayList集合,LinkedList集合多实现了一个Deque接口,这是一个双向队列接口,双向队列接口就是两端都可以进行增加和删除操作。
二、字段属性
// 链表元素(节点)的个数
transient int size = 0;
/**
* Pointer to first node.指向第一个节点的指针
*/
transient Node<E> first;
/**
* Pointer to last node.指向最后一个节点的指针
*/
transient Node<E> last;
注意这里出现了一个Node类,这是LinkedList类中的内部类,其中每一个元素就代表一个Node类对象,LinkedList集合就是由许多个Node对象类似于手拉着手构成。
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;
}
}
三、构造函数
/**
* Constructs an empty list.
*/
public LinkedList() {
}
/**
* Constructs a list containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
*
* @param c the collection whose elements are to be placed into this list
* @throws NullPointerException if the specified collection is null
*/
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
LinkedList有两个构造函数,第一个是默认的空的构造函数,第二个是将已有元素的集合Collection的实例添加到LinkedList中,调用的是addAll()方法,这个方法下面介绍。
注意:LinkedList是没有初始化链表大小的构造函数,因为链表不像数组,一个定义好的数组是必须要有确定的大小,然后去分配内存空间,而链表不一样,它没有确定的大小,通过指针的移动来指向下一个内存地址的分配。
四、添加元素
①、void addFirst(E e) 将指定元素添加到链表头
/**
* Inserts the specified element at the beginning of this list.
* 将指定的元素附加到链表头节点
* @param e the element to add
*/
public void addFirst(E e) {
linkFirst(e);
}
/**
* Links e as first element.
*/
private void linkFirst(E e) {
//将头节点赋值给 f
final Node<E> f = first;
//将指定元素构造成一个新节点,此节点的指向下一个节点的引用为头节点
final Node<E> newNode = new Node<>(null, e, f);
//将新节点设为头节点,那么原先的头节点 f 变为第二个节点
first = newNode;
//如果第二个节点为空,也就是原先链表为空
if (f == null)
//将这个新节点也设为尾节点,前面已经设为头节点了
last = newNode;
else
//将原先的头节点的上一个节点指向新节点
f.prev = newNode;
//节点数加1
size++;
//和ArrayList中一样,iterator和listIterator方法返回的迭代器和列表迭代器实现使用
modCount++;
}
②、public void addLast(E e) 和 public boolean add(E e) 将指定元素添加到链表尾
// 将元素添加到链表末尾
public boolean add(E e) {
linkLast(e);
return true;
}
// 将元素添加到链表末尾
public void addLast(E e) {
linkLast(e);
}
// 被其他方法调用的真正实现链表末尾添加算法
void linkLast(E e) {
// 将l设为尾节点
final Node<E> l = last;
// 构造一个新节点,节点上一个节点引用指向尾节点l
final Node<E> newNode = new Node<>(l, e, null);
// 将尾节点设为创建的新节点
last = newNode;
// 如果尾节点为空,表示原先链表为空
if (l == null)
// 将头节点设为新创建的节点(尾节点也是新创建的节点)
first = newNode;
else
// 将原来尾节点下一个节点的引用指向新节点
l.next = newNode;
// 节点数加1
size++;
// 和ArrayList中一样,iterator和listIterator方法返回的迭代器和列表迭代器实现使用
modCount++;
}
③、public void add(int index, E element) 将指定的元素插入此列表中的指定位置
/**
* 将指定的元素插入此列表中的指定位置
*/
public void add(int index, E element) {
// 判断索引 index >=0 && index <=size中时抛出IndexOutOfBoundsException异常
checkPositionIndex(index);
// 如果索引值等于链表大小
if (index == size)
//将节点插入到尾节点
linkLast(element);
else
//
linkBefore(element, node(index));
}
// 被其他方法调用的真正实现链表末尾添加算法
void linkLast(E e) {
// 将l设为尾节点
final Node<E> l = last;
// 构造一个新节点,节点上一个节点引用指向尾节点l
final Node<E> newNode = new Node<>(l, e, null);
// 将尾节点设为创建的新节点
last = newNode;
// 如果尾节点为空,表示原先链表为空
if (l == null)
// 将头节点设为新创建的节点(尾节点也是新创建的节点)
first = newNode;
else
// 将原来尾节点下一个节点的引用指向新节点
l.next = newNode