一、LinkedList简介
LinkedList的底层是一个双向的链表。链表的优点是加入一个元素,链表长度增加1,不会有冗余。
二、构造方法
1、LinkedList()
仅创建LinkedList对象,底层的链表为空。
2、LinkedList(Collection<? extends E> c)
将集合对象转换为数组,再将数组中的元素加入链表中,成为链表中的节点。
三、节点
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.add(E))通过新建节点实现:
新建一个节点,将入参元素加入节点内。将节点放在原链表的最后一个位置,并更新链表最后一个位置的节点为这个新建的节点。
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);//新建一个节点
last = newNode;//将新建的节点标记为链表中最后一个节点
if (l == null)
first = newNode;//如果是第一次添加元素,则将这个节点标记为链表首个节点
else
l.next = newNode;//如果插入元素之前链表中已有节点,则将原链表最后一个节点的下个节点变量置为新建的节点
size++;
modCount++;
}
LinkedList.addFirst(E)方法是用来增加一个节点到链表首部,源码与上面的方法类似,需要注意的是:两种方法新建节点时,Node对象构造方法参数有些区别。在链表首部插入节点方法的源码比较简单,不再赘述。
五、获取元素
LinkedList通过索引查找元素的效率比ArrayList慢,LinkedList先判断索引处于链表的前半部分还是后半部分。如果索引处于前半部分,则从首节点开始向后查找;如果索引处于后半部分,则从尾节点开始向前查找。
六、移除元素
先看张图:
- 将要删除节点前一个节点对象的下一个节点变量,指向要删除节点后一个节点;
- 将要删除节点后一个节点对象的上一个节点变量,指向要删除节点前一个节点;
- 要删除的节点此时已脱离链表,等待GC回收。
七、LinkedList与ArrayList的区别
- ArrayList的底层是一个可变数组,LinkedList底层是一个链表;
- ArrayList通过索引查找元素的效率高,时间复杂度为O(1);LinkedList通过索引查找元素的效率慢,时间复杂度为O(n);
- LinkedList插入删除元素的效率高,ArrayList插入删除元素的效率慢。