数据结构复习之LinkedList源码分析

数据结构复习之LinkedList源码分析

测试样例代码

package SourceTest;

import java.util.LinkedList;

public class LinkedListTest {
    public static void main(String[] args) {
        LinkedList list = new LinkedList();
        list.add("Hello");
        list.add("World");
        String string = (String) list.get(1);
        System.out.println();
    }
}

先对源码的变量进行分析

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
    transient int size = 0;

    /** * Pointer to first node. * Invariant: (first == null && last == null) || * (first.prev == null && first.item != null) */
    transient Node<E> first;

    /** * Pointer to last node. * Invariant: (first == null && last == null) || * (last.next == null && last.item != null) */
    transient Node<E> last;
  • 观察LinkedList类定义的变量为size、first头节点、last尾节点

对LinkedList的add方法进行分析

 public boolean add(E e) {
        linkLast(e);
        return true;
    }
  • 进入linkLast方法,传入一个输入的元素
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++;
    }
  • 将尾节点赋值给Node

  • 创建新节点保存原来尾节点、要插入的元素的值、和对应指针

  • 进入Node类可以看到Node是LinkedList的一个静态内部类,提供一个有参构造,从参数可以看出LinkedList底层维护的是一个双向链表

  • 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;
            }
        }
    
  • 之后回到linkLast方法,将新添加的元素赋值给last,即运用尾插法向双向链表中插入元素

  • if判断原last节点是否为空,不为空将l.next指向新插入节点。形成如下结构

  • 将链表长度增加

对LinkedList的get方法进行源码分析

public E get(int index) {
        checkElementIndex(index);
        return node(index).item;
    }
  • 可以看出get方法只调用checkElementIndex方法,传入一个int的索引,进入checkElementIndex方法

  •     private void checkElementIndex(int index) {
            if (!isElementIndex(index))
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }
    
  • 调用了isElementIndex方法用来判断元素索引,追踪可以看到只要index大于0并小于当前链表长度就可以

  •     private boolean isElementIndex(int index) {
            return index >= 0 && index < size;
        }
    
  • 以上代码相当于判断我们输入的index是否正确,如果正确调用node()方法,返回取到的值,进入node方法进行追踪

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;
            return x;
        } else {
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }
  • 可以看到进行if判断,判断的内容为我们的index是否小于size的一半(位右移运算1位相当于乘以2^-1)
  • 之后进行元素的查找,可以看出以这样的方法判断一下元素的位置可以缩短我们查找的时间,提高效率。相当于一次二分查找。利用了双向链表的优势
  • 之后找到元素返回结果

总结:

  • LinkedList底层维护了双向链表。在jdk1.8中是进行尾插操作
  • 进行get方法时会根据传入元素位置进行一次二分查找,优化查找性能
全部评论

相关推荐

沉淀一会:**圣经 1.同学你面试评价不错,概率很大,请耐心等待;2.你的排名比较靠前,不要担心,耐心等待;3.问题不大,正在审批,不要着急签其他公司,等等我们!4.预计9月中下旬,安心过节;5.下周会有结果,请耐心等待下;6.可能国庆节前后,一有结果我马上通知你;7.预计10月中旬,再坚持一下;8.正在走流程,就这两天了;9.同学,结果我也不知道,你如果查到了也告诉我一声;10.同学你出线不明朗,建议签其他公司保底!11.同学你找了哪些公司,我也在找工作。
点赞 评论 收藏
分享
10-17 12:16
同济大学 Java
7182oat:快快放弃了然后发给我,然后让我也泡他七天最后再拒掉,狠狠羞辱他一把😋
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务