上一篇写了ArrayList,其实还有一个较为常用的List,叫做LinkedList
LinkedList即实现了List接口,又实现了Deque接口,而Deque又继承Queue,所以LinkedList既是List,也是Deque,又是Queue;再加上在java中,stack也是通过Deque模拟的
所以:LinkedList在java中可以作为List,Deque,Queue,Stack
LinkedList内部维护了什么
LinkedList内部维护了两个重要属性:first–第一个节点 last–末尾节点
transient Node<E> first; //指向第一个节点
transient Node<E> last; //指向最后一个节点
每个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;
}
}
因为LinkedList实现了Deque接口,可以作为双端队列使用,必然有两个属性是指向前后两个节点
先new一个LinkedList
LinkedList linklist = new LinkedList<>();
public LinkedList() {
}
???除了开辟堆内存,居然啥都没干
===========================================================================================
这里讲述作为List接口实现的方法
add一个元素
linklist.add(“111”);
public boolean add(E e) {
linkLast(e); //顾名思义,该方法是将元素作为最后一个元素添加
return true;
}
void linkLast(E e) {
final Node<E> l = last; //先用一个变量指向最后一个Node(马上就不是了),last也可能是null(当第一次添加元素时)
final Node<E> newNode = new Node<>(l, e, null);
//new一个Node节点,将这个节点的prev属性指向原先的最后一个Node或者null,
//然后用item指向的对象e,newx指向null
last = newNode; //将内部维护的last变量指向这个新的末尾节点
if (l == null) //如果l为null,说明这是第一次添加元素,那么first变量也需要指向这个节点
first = newNode;
else //如果不是第一次添加,那么需要将
l.next = newNode;
size++; //实际元素个数++
modCount++; //修改次数++
}
注:linkLas(E e)这个方法很重要,在实现Queue的offer方法和实现Deque的offerLast方法中都调用了此方法,都是一样的原理,在每个Node内部维护两个属性,指向前后的Node以此来构建一条连续的链
通过源码可以发现,不同于ArrayList在内部维护数组,将所有的元素都放到数组中,LinkedList其实只能够直接地知道第一个节点和末尾节点,这两个节点之间的节点,其实是无法直接地获取的,需要通过这两个节点的next或者prev一个个遍历,才能找到需要的某个节点。所有节点是随机地在堆内存中开辟一块空间,不是连续的