Java基础相关

LinkedList简介

2020-04-09  本文已影响0人  Sincerity_

LinkedList概述

LinkedList底层通过双向集合的数据结构实现,LinkedList可以作为List使用,也可以作为队列和栈使用。支持从集合的头部,中间,尾部进行添加、删除等操作。LinkedList的继承与实现的关系图如下所示。

LinkedL ist继承与实现的关系图.jpg 双链表结构示意图.png
  // 一个私有的内部类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;
        }
    }

预热Deque接口

看看源码怎么说

添加Add

//调用add默认会添加到链表末尾
public boolean add(E e) {
        linkLast(e);
        return true;
    }
void linkLast(E e) {
        //得到最后一个节点的指针,
        final Node<E> l = last;
        //封装一个节点 l为前一个节点引用地址 e真正存储的数据,后面存放后一个节点的引用
        final Node<E> newNode = new Node<>(l, e, null);
        //最后一个节点指向新增的节点地址
        last = newNode;
        if (l == null)
            //空链表中新添加的节点就是第一个
            first = newNode;
        else
            //非空链表中新添加的节点就是链表最后节点的下一个节点
            l.next = newNode;
        //链表长度
        size++;
        //扩容次数
        modCount++;
    }

void add(int index, E element)

add(int index, E element)的逻辑稍显复杂,可以分成两部,

1.先根据index找到要插入的位置;

2.修改引用,完成插入操作。

 public void add(int index, E element) {
        //位置索引检测 return index >= 0 && index <= size;
        checkPositionIndex(index);
        if (index == size)
            //末尾插入 详情见上面
            linkLast(element);
        else
            //根据位置插入数据 node(index)得到index位置的节点
            linkBefore(element, node(index));
    }
//处理index位置的节点succ
void linkBefore(E e, Node<E> succ) {
        //得到succ的前驱指针
        final Node<E> pred = succ.prev;
        //创建newNode节点,将newNode的后继指针指向succ,前驱指针指向pred
        final Node<E> newNode = new Node<>(pred, e, succ);
        //将succ的前驱指针指向newNode
        succ.prev = newNode;
        if (pred == null)
            //前驱指针为空 就是第一个节点
            first = newNode;
        else
            //前驱指针不为空 那么直接将pred的后继指针指向newNode即可
            pred.next = newNode;
        size++;
        modCount++;
    }
双链表添加元素示意图.png

删除

public boolean remove(Object o) {
        //空对象的处理
        if (o == null) {
            //遍历节点
            for (Node<E> x = first; x != null; x = x.next) {\
                //节点数据为null
                if (x.item == null) {
                    unlink(x);
                    return true;
                }
            }
        } else {
            for (Node<E> x = first; x != null; x = x.next) {
                //节点数据和传递过来的数据一致
                if (o.equals(x.item)) {
                    unlink(x);
                    return true;
                }
            }
        }
        return false;
    }
 E unlink(Node<E> x) {
        //节点数据
        final E element = x.item;
        //节点的后驱指针指向的节点 后节点
        final Node<E> next = x.next;
        //节点的前驱指针指向的节点 前一个节点
        final Node<E> prev = x.prev;
        //前节点为空 表示删除第一个元素
        if (prev == null) {
            first = next;
        } else {
            //不为空就把前节点的后驱指针指向后节点
            prev.next = next;
            //当前节点的前驱指针指为空
            x.prev = null;
        }
        //后节点为空
        if (next == null) {
            //最后一个节点等于前节点
            last = prev;
        } else {
            //后节点的前驱指针指向前节点
            next.prev = prev;
            //当前节点的前驱指针指为空
            x.next = null;
        }
        //当前节点的前驱指针指为空
        x.item = null;
        size--;
        modCount++;
        return element;
    }

总结

和ArrayList的对比

其实就是链表和数组的对比。插入,删除:

查询

上一篇下一篇

猜你喜欢

热点阅读