数据结构复习之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方法时会根据传入元素位置进行一次二分查找,优化查找性能
全部评论

相关推荐

11-27 17:35
已编辑
蚌埠坦克学院 C++
深信服 后台开发 n×12
点赞 评论 收藏
分享
10-21 23:48
蚌埠坦克学院
csgq:可能没hc了 昨天一面完秒挂
点赞 评论 收藏
分享
10-16 09:58
已编辑
门头沟学院 Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务