1 LinkedList的数据结构
LinkedList底层维护了一个双向链表。根据下图所知,LinkedList集合中有两个属性,first和last分别指向首节点和尾节点。每个节点对象(Node对象),里面又维护了prev、next、item三个属性,其中prev指向前一个节点,next指向后一个节点,最终实现双向链表。这样也意味着,LinkedList中的元素的增加与删除的效率高于ArrayList【底层通过数组结构实现】。仅仅只需要修改节点prev、next的指向即可。
节点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;
}
}
2 自定义实现双向节点
public class MyLinkedList {
public static void main(String[] args) {
Node node1=new Node("1");
Node node2=new Node("2");
Node node3=new Node("3");
node1.next=node2;
node2.next=node3;
node3.prev=node2;
node2.prev=node1;
Node first=node1;
Node last=node3;
//从头进行遍历
System.out.println("从头进行遍历");
while (first!=null){
System.out.println(first);
//移动指针到下一个节点
first=first.next;
}
//从尾进行遍历
System.out.println("从尾进行遍历");
while (last!=null){
System.out.println(last);
//移动指针到下一个节点
last=last.prev;
}
//插入新的节点 node1 new node2
Node newNode=new Node("new");
node1.next=newNode;
newNode.next=node2;
node2.prev=newNode;
newNode.prev=node1;
//首节点重新置位
first=node1;
//插入节点后从新进行遍历
System.out.println("插入节点后重新进行遍历");
while (first!=null){
System.out.println(first);
//移动指针到下一个节点
first=first.next;
}
//删除节点 node3
node2.next=last;
//首节点重新置位
first=node1;
//插入节点后从新进行遍历
System.out.println("删除节点 node3重新进行遍历");
while (first!=null){
System.out.println(first);
//移动指针到下一个节点
first=first.next;
}
}
}
class Node<T>{
//结点内容
T item;
//指向前一个节点
Node prev;
//指向下一个节点
Node next;
Node(T item){
this.item=item;
}
@Override
public String toString() {
return "Node{" +
"item=" + item +
'}';
}
}
运行输出如下
从头进行遍历
Node{item=1}
Node{item=2}
Node{item=3}
从尾进行遍历
Node{item=3}
Node{item=2}
Node{item=1}
插入节点后重新进行遍历
Node{item=1}
Node{item=new}
Node{item=2}
Node{item=3}
删除节点 node3重新进行遍历
Node{item=1}
Node{item=new}
Node{item=2}
3 LinkedList源码分析
public static void main(String[] args) {
//构造函数
// public LinkedList() {} 此时 first与last 属性的值为null,
LinkedList list = new LinkedList();
//向尾部链接新的元素
// 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++; //修改链表对象变更的次数
// }
list.add(1);
list.add(2);
list.add(3);
删除元素【删除第一个元素】 f=first
// private E unlinkFirst(Node<E> f) {
// final E element = f.item;
// final Node<E> next = f.next; //next节点指向节点2
// f.item = null;
// f.next = null; //断开原来的首节点与下一个节点间的关系
// first = next; //首节点指向节点2
// if (next == null)
// last = null;
// else
// next.prev = null; 首节点的前一个节点为空
// size--; //节点长度减一
// modCount++; //
// return element; 返回删除的节点内容值 即为一
// }
list.remove();
System.out.println(list);
}
list.add(1)执行时源码分析
list.add(2)执行时源码分析
list.remove();执行时源码分析
分析源码可知,LinkedList中元素的新增与删除只要是变动节点间的prev、next之间的指向。在调试源码的过程中,可以加深对LinkedList方法的理解