zoukankan      html  css  js  c++  java
  • LinkedList 的实现原理

    概述

    LinkedList 和 ArrayList 一样,都实现了 List 接口,但其内部的数据结构有本质的不同。LinkedList 是基于链表实现的(通过名字也能区分开来),所以它的插入和删除操作比 ArrayList 更加高效。但也是由于其为基于链表的,所以随机访问的效率要比 ArrayList 差。

    看一下 LinkedList 的类的定义:

    public class LinkedList<E>
        extends AbstractSequentialList<E>
        implements List<E>, Deque<E>, Cloneable, java.io.Serializable
    {}

    LinkedList 继承自 AbstractSequenceList,实现了 List、Deque、Cloneable、java.io.Serializable 接口。AbstractSequenceList 提供了List接口骨干性的实现以减少实现 List 接口的复杂度,Deque 接口定义了双端队列的操作。

    在 LinkedList 中除了本身自己的方法外,还提供了一些可以使其作为栈、队列或者双端队列的方法。这些方法可能彼此之间只是名字不同,以使得这些名字在特定的环境中显得更加合适。

    LinkedList 也是 fail-fast 的(前边提过很多次了)。

    LinkedList 源码解读

    数据结构

    LinkedList 是基于链表结构实现,所以在类中包含了 first 和 last 两个指针(Node)。Node 中包含了上一个节点和下一个节点的引用,这样就构成了双向的链表。每个 Node 只能知道自己的前一个节点和后一个节点,但对于链表来说,这已经足够了。

        transient int size = 0;
        transient Node<E> first; //链表的头指针
        transient Node<E> last; //尾指针
        //存储对象的结构 Node, 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;
            }
        }

    存储

    add(E e)

    该方法是在链表的 end 添加元素,其调用了自己的方法 linkLast(E e)。

    该方法首先将 last 的 Node 引用指向了一个新的 Node(l),然后根据l新建了一个 newNode,其中的元素就为要添加的 e;而后,我们让 last 指向了 newNode。接下来是自身进行维护该链表。

    /**
         * Appends the specified element to the end of this list.
         *
         * <p>This method is equivalent to {@link #addLast}.
         *
         * @param e element to be appended to this list
         * @return {@code true} (as specified by {@link Collection#add})
         */
    public boolean add(E e) {
        linkLast(e);
        return true;
    }
    /**
    * Links e as last element.
    */
    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++;
    }

    add(int index, E element)

    该方法是在指定 index 位置插入元素。如果 index 位置正好等于 size,则调用 linkLast(element) 将其插入末尾;否则调用 linkBefore(element, node(index))方法进行插入。该方法的实现在下面,大家可以自己仔细的分析一下。(分析链表的时候最好能够边画图边分析)

    /**
        * Inserts the specified element at the specified position in this list.
        * Shifts the element currently at that position (if any) and any
        * subsequent elements to the right (adds one to their indices).
        *
        * @param index index at which the specified element is to be inserted
        * @param element element to be inserted
        * @throws IndexOutOfBoundsException {@inheritDoc}
        */
       public void add(int index, E element) {
           checkPositionIndex(index);
    
           if (index == size)
               linkLast(element);
           else
               linkBefore(element, node(index));
       }
       /**
            * Inserts element e before non-null Node succ.
            */
           void linkBefore(E e, Node<E> succ) {
               // assert succ != null;
               final Node<E> pred = succ.prev;
               final Node<E> newNode = new Node<>(pred, e, succ);
               succ.prev = newNode;
               if (pred == null)
                   first = newNode;
               else
                   pred.next = newNode;
               size++;
               modCount++;
           }

    LinkedList 的方法实在是太多,在这没法一一举例分析。但很多方法其实都只是在调用别的方法而已,所以建议大家将其几个最核心的添加的方法搞懂就可以了,比如 linkBefore、linkLast。其本质也就是链表之间的删除添加等。

  • 相关阅读:
    centos8 将SSSD配置为使用LDAP并要求TLS身份验证
    Centos8 搭建 kafka2.8 .net5 简单使用kafka
    .net core 3.1 ActionFilter 拦截器 偶然 OnActionExecuting 中HttpContext.Session.Id 为空字符串 的问题
    Springboot根据不同环境加载对应的配置
    VMware Workstation12 安装 Centos8.3
    .net core json配置文件小结
    springboot mybatisplus createtime和updatetime自动填充
    .net core autofac依赖注入简洁版
    .Net Core 使用 redis 存储 session
    .Net Core 接入 RocketMQ
  • 原文地址:https://www.cnblogs.com/baojun/p/11087015.html
Copyright © 2011-2022 走看看