LinkedList-JDK17

3 阅读6分钟

       LinkedList,链表,一个节点挂着另外一个节点
       优点在哪儿?往这个里面中间插入一些元素,或者不停的往list里插入元素,都没关系,因为人家是链表,中间插入元素,不需要跟ArrayList数组那样子,挪动大量的元素的,不需要,人家直接在链表里加一个节点就可以了
       如果你不断的往LinkedList中插入一些元素,大量的插入,就不需要像ArrayList数组那样还要去扩容啊什么的,人家是一个链表,就是不断的把新的节点挂到链表上就可以了
       LinkedList的优点,就是非常适合各种元素频繁的插入里面去
       LinkedList的缺点,不太适合在随机的位置,获取某个随机的位置的元素,比如LinkedList.get(10),这种操作,性能就很低,因为他需要遍历这个链表,从头开始遍历这个链表,直到找到index = 10的这个元素为止
       ArrayList.get(10),不需要遍历,直接根据内存的地址,根据你指定的index,直接定位到那个元素,不需要遍历数组什么的
       ArrayList和LinkedList区别,数组和链表的区别,优缺点主要就是这样子
       LinkedList:适合,频繁的在list中插入和删除某个元素,然后尤其是LinkedList他其实是可以当做队列来用的,先进先出,在list尾部怼进去一个元素,从头部拿出来一个元素。如果要在内存里实现一个基本的队列的话,可以用LinkedList

image.png

public boolean add(E e) {
//核心添加逻辑
    linkLast(e);
    //固定返回
    return true;
}


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++;
}

public void add(int index, E element) {
//索引边界检查
    checkPositionIndex(index);

//选择插入策略
    if (index == size)
        linkLast(element);//情况1,尾部插入
    else
    //情况2,在指定节点插入
    //根据给定的 `index` 找到双向链表中的对应节点
        linkBefore(element, node(index));
}
Node<E> node(int index) {
    // assert isElementIndex(index);

    if (index < (size >> 1)) {
    //从前往后遍历
        Node<E> x = first;//从头节点开始
        for (int i = 0; i < index; i++)
            x = x.next;//向后移动indexreturn x;//返回目标节点
    } else {
    //从后往前遍历
    //从尾节点开始
        Node<E> x = last;
        //向前移动(size-1-index)
        for (int i = size - 1; i > index; i--)
            x = x.prev;
            //返回目标节点
        return x;
    }
}
public void addFirst(E e) {
    linkFirst(e);
}


private void linkFirst(E e) {
    final Node<E> f = first;//暂存原头节点
    final Node<E> newNode = new Node<>(null, e, f);//创建新节点(prev=null, next指向原头节点)
    
    first = newNode;//更新头指针指向新节点
    
    //处理链表状态
    if (f == null)
        last = newNode;//原链表为空-->新节点也是尾节点
    else
        f.prev = newNode;//原链表非空-->原头节点的prev指向新节点
    size++;//元素数量+1
    modCount++;//结构性修改计数+1(支持迭代器快速失败)
}

LinkedList可以作为一个队列来使用

offer() == add(),就是在队列尾部入队,将一个元素插入队列尾部,
offerFirst()头部插入元素,offerLast()尾部插入元素
poll(),从队列头部出队
peek(),获取队列头部的元素,但是头部的元素不出队

public boolean offer(E e) {
    return add(e);
}
public boolean offerFirst(E e) {
    addFirst(e);
    return true;
}
public boolean offerLast(E e) {
    addLast(e);
    return true;
}
public E poll() {
//获取链表头节点
    final Node<E> f = first;
    //若头节点为空,则返回空。否则调用unlinkFirst(f)移除头节点
    return (f == null) ? null : unlinkFirst(f);
}
private E unlinkFirst(Node<E> f) {
//断言 f必须是头节点且非null
    // assert f == first && f != null;
    
    //获取头节点存储的元素值
    final E element = f.item;
    
    //获取头节点的后继节点(可能为null)
    final Node<E> next = f.next;
    
    //清空节点引用(帮助GC回收)
    f.item = null;
    f.next = null; // help GC 断开头节点与链表连接
    
    //更新头节点指向后继节点
    first = next;
    
    //处理链表状态
    if (next == null)
    //情况A 无后续节点
        last = null;
    else
    //情况B 后继节点成为新头节点,需清空前驱指针
        next.prev = null;
        
        //更新元数据
    size--;//元素计数减1
    modCount++;//结构性修改计数+1
    return element;
}
public E peek() {
    final Node<E> f = first;
    return (f == null) ? null : f.item;
}
public E get(int index) {
    checkElementIndex(index);//索引合法性校验
    return node(index).item;
}
public E getLast() {
    final Node<E> l = last;
    if (l == null)
        throw new NoSuchElementException();
    return l.item;
}
public E getFirst() {
    final Node<E> f = first;
    if (f == null)
        throw new NoSuchElementException();
    return f.item;
}
list.remove();
public E remove() {
    return removeFirst();
}
public E removeFirst() {
    final Node<E> f = first;
    if (f == null)
        throw new NoSuchElementException();
    return unlinkFirst(f);
}
private E unlinkFirst(Node<E> f) {

    // assert f == first && f != null;
    final E element = f.item;//保存被删节点的数据,用于返回
    final Node<E> next = f.next;//保存后继节点(新头节点候选)
    f.item = null; //清空旧头节点引用(GC优化)
    f.next = null; // help GC,显式断开引用,加速垃圾回收
    first = next;  //头节点指向后继节点(新头节点)
    if (next == null) //链表仅有一个节点
        last = null;  //清空尾指针(链表变空)
    else
        next.prev = null; //新头节点前驱置空(断开与旧节点的联系)
    size--; //元素数量减1
    modCount++;//结构性修改计数+1(触发迭代器快速失败)
    return element;
}

list.remove("test");
public boolean remove(Object o) {
    if (o == null) {
        for (Node<E> x = first; x != null; x = x.next) {
            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;
}


list.remove(1);
public E remove(int index) {
    checkElementIndex(index);
    return unlink(node(index));
}
E unlink(Node<E> x) {
    // assert x != null;
    //保存被删节点的数据
    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;
        //断开目标节点对前驱的引用(加速GC)
        x.prev = null;
    }

//目标节点是尾节点
    if (next == null) {
    //更新尾指针指向前驱节点
        last = prev;
    } else {//目标节点非尾节点
    //后继节点直接链接到前驱节点
        next.prev = prev;
        //断开目标节点对后继的引用
        x.next = null;
    }

//清空数据引用
    x.item = null;
    //元素数量减1
    size--;
    //结构性修改计数+1(触发迭代器快速失败)
    modCount++;
    //返回被删除的数据
    return element;
}

list.removeFirst();
public E removeFirst() {
    final Node<E> f = first;
    if (f == null)
        throw new NoSuchElementException();
    return unlinkFirst(f);
}
private E unlinkFirst(Node<E> f) {
    // assert f == first && f != null;
    final E element = f.item;
    final Node<E> next = f.next;
    f.item = null;
    f.next = null; // help GC
    first = next;
    if (next == null)
        last = null;
    else
        next.prev = null;
    size--;
    modCount++;
    return element;
}

list.removeLast();
public E removeLast() {
    final Node<E> l = last;
    if (l == null)
        throw new NoSuchElementException();
    return unlinkLast(l);
}
private E unlinkLast(Node<E> l) {
    // assert l == last && l != null;
    //保存尾节点的数据(用于返回)
    final E element = l.item;
    //保存尾节点的前驱节点
    final Node<E> prev = l.prev;
    //清空旧尾节点引用(GC优化)
    l.item = null;
    l.prev = null; // help GC.显示断开引用,加速垃圾回收
    //尾指针指向前驱节点(新尾节点)
    last = prev;
    //链表只有一个节点
    if (prev == null)
    //清空头指针(链表变空)
        first = null;
    else
    //新尾节点的next置空-尾部无后继
        prev.next = null;
    size--; //元素数量减1
    modCount++;
    return element;
}