概述
LinkedList 是通过一个双向链表来实现的,它允许插入所有元素,包括 null,同时,它是线程不同步的。
1、 LinkedList 的底层结构是一个
带头/尾指针的双向链表
,可以快速的对头/尾节点进行操作。
2、相比数组,链表的特点就是在
指定位置插入和删除元素的效率较高
,但是
查找的效率就不如数组那么高
了
常用的方法
双向链表,
头节点均指first,尾节点均指last
添加元素:
add(E e):将元素添加到表尾,
返回布尔类型值
addFirst(E e):添加新的头节点
addLast(E e):添加新的尾节点
add(int index,E e):在指定位置插入节点
push(E e):将元素添加到头节点
获取元素:
getFirst():获取头节点
getLast():获取尾部节点
node(int index):获取指定下标的节点
get(int index):获取指定下标的节点
peek():返回头节点
element():返回头节点
删除元素:
remove(Object o):删除指定节点,返回布尔类型值
remove(int index):删除指定节点的下标,返回删除的值
removeFirst():删除头节点,返回头节点的值
removeLast():删除尾节点,返回尾节点的值
poll():获取头节点,并删除头节点
替换元素:
set(int index,E e):将下标为index的节点替换为新的值,返回被替换的值
1.属性
//链表的节点个数
transient int size = 0;
//指向头节点的指针
transient Node<E> first;
//指向尾节点的指针
transient Node<E> last;
2.方法
1.节点结构
Node 是在 LinkedList 里定义的一个静态内部类,它表示链表每个节点的结构,包括一个数据域 item,一个后置指针 next,一个前置指针 prev。
private static class Node{
E item;//节点内容
Node<E> next;
Node<E> pre;
//构造方法
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
2.添加元素
对于链表,添加元素的操作即在表头/表尾插入元素,又或者在指定位置插入元素。因为 LinkedList 有头指针和尾指针,所以在表头或表尾进行插入元素只需要 O(1) 的时间,而在指定位置插入元素则需要先遍历一下链表,所以复杂度为 O(n)。
当向表头插入一个节点时,很显然当前节点的前驱一定为 null,而后继结点是 first指针指向的节点,当然还要修改 first 指针指向新的头节点。此外,原来的头节点变成了第二个节点,因此修改原来头节点的前驱指针,使它指向表头节点。
private void linkFirst(E e) {
final Node<E> f = first;
//当前节点的前驱指向 null,后继指针原来的头节点
final Node<E> newNode = new Node<>(null, e, f);
//头指针指向新的头节点
first = newNode;
//如果原来有头节点,则更新原来节点的前驱指针,否则更新尾指针
if (f == null)
last = newNode;
else
f.prev = newNode;
size++;
modCount++;
}
//向表尾添加元素
void linkLast(E e) {
final Node<E> l = last;
//当前节点的前驱指向尾节点,后继指向 null
final Node<E> newNode = new Node<>(l, e, null);
<