转载:http://wiki.jikexueyuan.com/project/java-collection/linkedlist.html

概述

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。其本质也就是链表之间的删除添加等。

LinkedList的实现原理的更多相关文章

  1. Java LinkedList的实现原理

    LinkedList是Java List类型的集合类的一种实现,此外,LinkedList还实现了Deque接口.本文基于Java1.8,对于LinkedList的实现原理做一下详细讲解. (Java ...

  2. Java-链表LinkedList源码原理分析,并且通过LinkedList构建队列

    在这里我们介绍一下最简单的链表LinkedList: 看一下add()方法: public boolean add(E e) { linkLast(e); return true; } void li ...

  3. Java集合之ArrayList和LinkedList的实现原理以及Iterator详解

    ArrayList实现可变数组的原理: 当元素超出数组内容,会产生一个新数组,将原来数组的数据复制到新数组中,再将新的元素添加到新数组中. ArrayList:是按照原数组的50%来延长,构造一个初始 ...

  4. LinkedList 底层实现原理

    LinkedList的底层实现原理 LinkedList 底层数据结构为双向链表,链表结构,基于一个个链表节点Node 1,Inner Class 内部类 private static class N ...

  5. JDK1.8中LinkedList的实现原理及源码分析

    详见:https://blog.csdn.net/cb_lcl/article/details/81222394 一.概述           LinkedList底层是基于双向链表(双向链表的特点, ...

  6. 集合总结二(LinkedList的实现原理)

    一.概述 先来看看源码中的这一段注释,我们先尝试从中提取一些信息: Doubly-linked list implementation of the List and Deque interfaces ...

  7. LinkedList 的实现原理

    本文为博客园作者所写: 一寸HUI,个人博客地址:https://www.cnblogs.com/zsql/ 简单的一个类就直接说了.LinkedList 的底层结构是一个带头/尾指针的双向链表,可以 ...

  8. LinkedList实现原理(JDK1.8)

    LinkedList实现原理(JDK1.8) LinkedList底层采用双向链表,如果对链表这种结构比较熟悉的话,那LinkedList的实现原理看明白就相当容易. 链表通过"指针&quo ...

  9. 计算机程序的思维逻辑 (39) - 剖析LinkedList

    上节我们介绍了ArrayList,ArrayList随机访问效率很高,但插入和删除性能比较低,我们提到了同样实现了List接口的LinkedList,它的特点与ArrayList几乎正好相反,本节我们 ...

随机推荐

  1. ads 的一些错误

    遇到动不动就有*.o文件找不到的情况,而且通常都是开始的时候可以正常LINK,而经过若干次重新LINK后却找不到(即使只是在代码中加一个无关紧要得空格),新建个工程,将目前的.C和.H文件原封不动加进 ...

  2. Leetcode: UTF-8 Validation

    A character in UTF8 can be from 1 to 4 bytes long, subjected to the following rules: For 1-byte char ...

  3. windows下nginx和php环境的配置

    至于php的配置,与之前博文中使用apache服务器时一样. 对于nginx的配置,来看看如何修改配置文件: #user nobody; worker_processes ; #error_log l ...

  4. java 网络编程(二)----UDP基础级的示例

    下面介绍UDP基础级的代码示例: 首先了解创建UDP传输的发送端的思路: 1.创建UDP的Socket服务.2.将要发送的数据封装到数据包中.3.通过UDP的socket服务将数据包发送出去.4.关闭 ...

  5. 【linux】自定义配置debian+openbox

    openbox确实是好东西阿,小巧,不开iceweasel时内存总使用量不到200M,功能又强大,不过限于我是菜鸟,openbox再强大也有限...debian装openbox是及其简单的,不过为了使 ...

  6. Yii2.0 查询(CRUD)

    yii2使用中的一些基本的增删改查操作.以用户为例说明: User::find()->all();    //返回所有用户数据:   User::findOne($id);   //返回 主键 ...

  7. DB2 Unload 的时候遇到B37-04

    B37-04的问题是每个Mainframer首先会遇到的问题,在Unload的时候最大的可能性是Extend次数到16次了,这时候只要加大primary或secondary就可以了,我最常用的是pri ...

  8. C++之: CDib类

    头文件Cdib.h 源文件Cdib.cpp

  9. python爬虫框架scrapy实例详解

    生成项目scrapy提供一个工具来生成项目,生成的项目中预置了一些文件,用户需要在这些文件中添加自己的代码.打开命令行,执行:scrapy st... 生成项目 scrapy提供一个工具来生成项目,生 ...

  10. 在HTML页面获取当前系统时间

    <script language="javascript"> function getCurDate() { var d = new Date(); var week; ...