1)LinkedList底层实现了双向链表和双端队列特点;
2)可以添加任何元素(元素可以重复),包括重复null值;
3)线程不安全,没有实现同步。
1)LinkedList底层维护了一个双向链表;
2)LinkedList中维护了两个属性first和last分别指向首节点和尾节点;
3)每个节点(Node对象),里面又维护了prev、next、item三个属性,其中通过prev指向前一个,通过next指向后一个节点,最终实现双向链表;
4)LinkedList的元素的添加和删除(通过改变node节点指针指向来实现增加删除和添加),不是通过数组完成的(数组需要扩容和元素复制),相对来说效率较高。
- transient Node
first; -
- transient Node
last; -
- private static class Node
{ - E item;
- Node
next; - Node
prev; -
- Node(Node
prev, E element, Node next) { - this.item = element;
- this.next = next;
- this.prev = prev;
- }
- }
- public class LinkedList1 {
- public static void main(String[] args) {
- //模拟一个简单的双向链表
- Node jack = new Node("jack");
- Node tom = new Node("tom");
- Node hsp = new Node("hsp");
- LinkedList linkedList = new LinkedList();
- //连接2个节点,形成双向链表
- //jack->tom->hsp
- jack.next = tom; //jack的后一个节点指向tom
- tom.next = hsp;//tom的后一个节点指向hsp
- //hsp->tom->jack
- hsp.prev = tom;//hsp的前一个节点指向tom
- tom.prev = jack;//tom的前一个节点指向jack
- Node first = jack;//让first引用指向jack,为双向链表的头节点
- Node last = hsp;//让last引用指向hsp,为双向链表的尾节点
-
- //从头到尾遍历
- 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;
- }
-
- //链表添加数据/对象
- Node smith = new Node("smith");
-
- smith.next = hsp;
- smith.prev = tom;
- tom.next = smith;
- hsp.prev = tom;
-
- first = jack;//双向链表的头节点
- System.out.println("---------从头到尾遍历--------");
- while (first != null) {
- System.out.println(first);
- first = first.next;
- }
-
-
- }
-
- //定义一个Node类,Node对象表示双向链表的一个节点
- static class Node {
- public Object item; //存放真正的元素
- public Node next; //指向后一个节点
- public Node prev; //指向前一个节点
-
-
- public Node(Object item) {
- this.item = item;
- }
-
- @Override
- public String toString() {
- return "Node{" +
- "item=" + item +
- '}';
- }
-
- }
- }
创建一个LinkedList无参构造对象,此时LinkedList的属:first = null last = null size = 0
- LinkedList linkedList = new LinkedList<>();
-
- //内部为一个无参构造方法
- //此时LinkedList的属:first = null last = null size = 0
- public LinkedList() {
- }
执行add(E e)方法向LinkedList中添加数据
- //第1次添加元素
- linkedList.add(1);
- //第2次添加元素
- linkedList.add(1);
-
- //执行add(E e)方法向LinkedList中添加一条数据
- public boolean add(E e) {
- linkLast(e);
- return true;
- }
-
-
- //将新的节点加入双向链表的最后
- void linkLast(E e) {
- //此时last为null,因此l=null
- final Node
l = last; - // 创建节点:首次添加元素1, l = null last = null e = 1
- // 创建节点:第二次添加元素2 之前l指向1,此时将l赋值给prev,此时prev指向1
- final Node
newNode = new Node<>(l, e, null); - //将last的指向新的节点->2,此时指向1的last断裂
- last = newNode;
- if (l == null)
- //首次添加元素 first(null)->1<-last(null)
- first = newNode;
- else
- //此时next指向2
- //first(null)->1<->2<-last(null)
- l.next = newNode;
- size++;
- modCount++;
- }
执行remove(int index)方法向LinkedList中移除数据
- linkedList.add(2);
- linkedList.add(3);
- linkedList.add(4);
- //移除下标为2的数据,移除元素3
- linkedList.remove(2);
- System.out.println("linkedList=" + linkedList);
- }
-
- public E remove(int index) {
- //判断下标是否越界
- checkElementIndex(index);
-
- return unlink(node(index));
- }
-
-
- E unlink(Node
x) { -
- // assert x != null;
- //此时指向关系为 first(null)->1<->2<->3<->4<-last(null)
- //获取下标为2的内容为3
- final E element = x.item;
- //获取下标为2的内容(3)的后一个指向,该指标指向4
- final Node
next = x.next; - //获取下标为2的内容(3)的前一个指向,该指标指向2
- final Node
prev = x.prev; -
- if (prev == null) {
- first = next;
- } else {
- //此时指标指向不为null
- //将3的下一个prev指向(4指向3的prev)去指向3的指向
- prev.next = next;
- //将3指向2的指向置为空,此时3指向2的prev消失 help GC
- x.prev = null;
- }
- //此时指标指向不为null
- if (next == null) {
- last = prev;
- } else {
- //将4的前一个指向指向3的前一个指向
- next.prev = prev;
- //将3的下一个指向置为空
- x.next = null;
- }
-
- x.item = null;
- size--;
- modCount++;
- return element;
- }
1)LinkedList底层实现了双向链表和双端队列特点;
2)可以添加任何元素(元素可以重复),包括重复null值;
3)线程不安全,没有实现同步。
1)LinkedList底层维护了一个双向链表;
2)LinkedList中维护了两个属性first和last分别指向首节点和尾节点;
3)每个节点(Node对象),里面又维护了prev、next、item三个属性,其中通过prev指向前一个,通过next指向后一个节点,最终实现双向链表;
4)LinkedList的元素的添加和删除(通过改变node节点指针指向来实现增加删除和添加),不是通过数组完成的(数组需要扩容和元素复制),相对来说效率较高。