![5ba52b43a8343f409511466b9f558389.png](https://i-blog.csdnimg.cn/blog_migrate/ed5bc71262ee18a32317d87c69e84b93.png)
- LinkedList集合的父接口是List---父接口是Collection.底层是双链表数据结构 查询比单 链表快,比数组慢。增删比数组快,比单链表慢。
2.看起来有些抽象,其实这个图是对底层代码的一种假想 现在我们看一下底层代码
//下面这段代码是个小栗子 向LinkedList集合中添加一个数据
import java.util.LinkedList;
public class Test01 {
public static void main(String[] args) {
LinkedList<Object> list = new LinkedList<>();
list.addLast(3); //我们主要看这里的源码
}
}
//下面是addLast的源码
public void addLast(E e) {
linkLast(e); //在addLast中实际上调用的是这个方法 继续进去看
}
//下面是linkLast(e); 方法源码
void linkLast(E e) { //这里的参数仍然是addlist添加的数据
final Node<E> l = last; //这里定义了一个节点变量l 把last赋值给l。
//last/first是LinkedList的成员变量,代表尾节点与头节点
//当创建集合对象时 默认值是null,
final Node<E> newNode = new Node<>(l, e, null); //此处是根据传进来的参数e也就是要添加的数据创建一个
//新节点,l存储的是前一个节点的地址,由于此时添加的数据是在集合末尾
//所以尾节点的后一个节点的地址值是null
last = newNode; //将当前节点地址值赋值给last,下一次在添加数据时,这个节点就是要添加的节点的前一个节点了
if (l == null) //此处判断l是不是null l存放的最开始的last,第一次添加数据last是null
first = newNode; //所以此节点是头节点 给first赋值
else //假如不是第一个添加的数据 此时将此节点地址给前一个节点的后一个指针域
l.next = newNode; 这样就实现了双链表数据结构
size++;
modCount++;
}
3.接下来我们在看一下获取数据的方法get()源码 加深理解
public E get(int index) {
checkElementIndex(index); //这里是检查参数索引 不用管
return node(index).item; //此处调用了node方法 看一下
}
//node方法
Node<E> node(int index) {
// assert isElementIndex(index);
if (index < (size >> 1)) { // >>符号是位运算 右移一位 相当于/2 此处判断索引index与集合长度一半的关系
Node<E> x = first; //index<size/2 把first首节点赋值给局部节点变量x
for (int i = 0; i < index; i++) //此处用循环 获取到index的节点
x = x.next;
return x;
} else {
Node<E> x = last; //如果>size/2,就从尾节点开始循环 找到index的节点
for (int i = size - 1; i > index; i--) //这种方法优点是以最少的查找次数找到index ,
return x; //其实可以理解为先判断index距离头和尾谁近,离谁近就从那边开始循环
x = x.prev;
}
}
4.好了就说到这里 双链表你理解了吗 图只是代码的抽象形式