LinkedList的底层实现原理

LinkedList 底层数据结构为双向链表,链表结构,基于一个个链表节点Node

1,Inner Class 内部类

private static class Node<E>{
    E item;//当前节点下的当前元素
    Node<E> next;//下一个节点
    Node<E> prev;//上一个节点

//constructor
    Node(Node<E>prev , E element , Node<E> next){
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}

2,属性 fields
transient size = 0;
transient Node<E> first;
transient Node<E> last;

//LinkedList 底层是链表结构,所以其属性就是封装了链表中一个有多少个节点,以及第一个节点,最后一个节点。

3,构造方法 constructor
//无参构造方法
public LinkedList(){

}
//public LinkedList(Collection <? extends E> c){
   this();
   addAll(size,c);
}

public boolean addAll(int index,Collection <? extends E>c){
    checkPositionIndex(index);

Object[] a = c.toArray();
    int numNew = a.length;
    if(numNew == 0)
        return false;
  
    Node<E> pred,succ;//pred 代表要有变化的前节点, succ 代表要变化的后节点
    例:{“good”,"bad","bye","see","to","two","you","me"} 要实现在index = 2 处insert 一个集合,那么Node<E> prev 就是“bad”所在的节点,Node<E> succ 就是"bye" 所在的节点。

if(index == size){
      succ = null;
      pred = last;
      //按着顺序插入的情况会相等,必须先插入长度为3的集合,然后顺着插入在index 为4 的位置继续插入
    }else{
      succ = node(index);//-[]-[]-[]-[]-[]/\-[]-[]  /\代表插入,succ 后节点就是/\ 之后的节点
      pred = succ.prev;
    }
   //开始插入
    for(Object o:a){
        @SupressWarnings("unchecked") E e  = (E)o;
        Node<E> newNode = new Node<>(pred,e,null);
        if(pred == null)
            first = newNode;
        else
           pred.next = newNode;
       pred = newNode;//为了循环中下一次的赋值,得把pred赋值成当前元素
    }
  
    if(succ == null){
        last = pred;
    }else{
        pred.next = succ;
        succ.prev = pred;
        //因为pred 在for 循环中插入时候一直有更新,所以这段代码的作用是为了将插入的最后一个节点后变化后的节点连接起来,形成一个新的链表。
    }
}

//找到即将有变化的节点,这个节点永远是变化的后节点
Node<E> node(int index){
    //二分法,如果变化在前半部分,则找出first 如果变化在后半部分,则找出last
    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;
        }
    }
}

private void checkPositionIndex(int index){
    if(!isPositionIndex(index))
        throw new IndexOutOfBoundsException(OutOfBoundsMsg(index));
}

private boolean isPositionIndex(index){
    return index >=0 && index <=size;
}

//addAll(int index,Collection<? extends E> c)这个方法可以用于LinkedList 的初始化中,
可以加载指定集合到目标集合中。
另外,这个方法也可以用于在目标集合指定位置插入指定集合。

4,add
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++;
}

//add方法中范型E控制add元素的类型,如果类型不对,则编译报错,否则不会出现异常。
在最后一个节点后面增加新元素,上一个节点是last,当前是e,下一个null,需要判断当前增加的是不是第一个元素,是则将新增元素赋值为链中的first,不是则将当前元素赋值为last的next元素。

5 addFirst
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);
    first = newNode;

//每增加一个节点,都要创建和已知节点的关联
    if(f == null)
        last = newNode;
    else
        f.prev = newNode;
    size++;
    modCount++;
}

6,addLast
调用的也是linkLast(E e)方法,和add(E e) 是调用一样的方法,只不过add(E e) 返回类型是boolean 型,addLast是void.

7,removeFirst

public E removeFirst(E e){
    final Node<E> f = first;
    if(f == null)
        throw new NoSuchElementException();

return unLinkFirst(f);
}

privte E unLinkFirst(Node<E> f){
    final E element = f.item;
    Node<E> next = f.next;
    //f 将删除,f的节点关系也需被删除
    f.item = null;
    f.next = null;
   
    first = next;
    if(next == null)
        last = next;
    else
        next.prev = null;

size--;
    modCount++;

return element;
}

8,removeLast

public E removeLast(E e){
    final Node<E> l = last;
    if(last == null)
        throw new NoSuchElementException();
    return unLinkLast(l);
}

private E unLinkLast(Node<E> l){
    final E element = l.item;
    fianl Node<E> prev = l.prev;
    //clear relationship
    l.item = null;
    l.prev = null;
    //重新设定
    last = prev;

if(prev == null)
        first = prev;
    else
        prev.next = null;

size--;
    modeCount++:
    return element;
}

9,getFirst

public E getFirst(){
    fianl Node<E> f = first;
    if(f == null)
        throw new NoSuchElementException();
    return f.item;
}

10,getLast

public E getLast(){
    final Node<E> l = last;
    if(l == null)
        throw new NoSuchElementException();
    return l.item;
}

11,查询

public E get(int index){
    CheckElementIndex(index);
    return node(index).item;//通过node方法获取到当前index 的节点
}

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

  1. HashMap、LinkedHashMap、ConcurrentHashMap、ArrayList、LinkedList 底层实现

    HashMap相关问题 1.你用过HashMap吗?什么是HashMap?你为什么用到它? 用过,HashMap是基于哈希表的Map接口的非同步实现,它允许null键和null值,且HashMap依托 ...

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

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

  3. PHP底层工作原理

    最近搭建服务器,突然感觉lamp之间到底是怎么工作的,或者是怎么联系起来?平时只是写程序,重来没有思考过他们之间的工作原理: PHP底层工作原理 图1 php结构 从图上可以看出,php从下到上是一个 ...

  4. LinkedList底层实现,及其数据结构实现。

    LinkedList底层的实现基于双向表 prev data next next指向下一个node的地址.prev指向上一个node. 这里的代码是LinkedList类的源码. private st ...

  5. Java并发之底层实现原理学习笔记

    本篇博文将介绍java并发底层的实现原理,我们知道java实现的并发操作最后肯定是由我们的CPU完成的,中间经历了将java源码编译成.class文件,然后进行加载,然后虚拟机执行引擎进行执行,解释为 ...

  6. spirng底层实现原理

    什么是框架?框架解决的是什么问题? 编程有一个准则,Don't Repeat Yourself(不要重复你的代码),所以我们会将重复的代码抽取出来,封装到方法中:如果封装的方法过多,将将这些方法封装成 ...

  7. iOS weak底层实现原理

    今年年底做了很多决定,离开工作三年的深圳,来到了上海,发现深圳和上海在苹果这方面还是差距有点大的,上海的市场8成使用swift编程,而深圳8成的使用OC,这点还是比较让准备来上海打拼的苹果工程师有点小 ...

  8. 《Java并发编程的艺术》Java并发机制的底层实现原理(二)

    Java并发机制的底层实现原理 1.volatile volatile相当于轻量级的synchronized,在并发编程中保证数据的可见性,使用 valotile 修饰的变量,其内存模型会增加一个 L ...

  9. Spring(二)IOC底层实现原理

    IOC原理 将对象创建交给Spring去管理. 实现IOC的两种方式 IOC配置文件的方式 IOC注解的方式 IOC底层实现原理 底层实现使用的技术 1.1 xml配置文件 1.2 dom4j解析xm ...

随机推荐

  1. 【pyqtgraph绘图】线条,填充和颜色

    解读官方API-线条,填充和颜色 参考: http://www.pyqtgraph.org/documentation/style.html 线条,填充和颜色 Qt依靠其QColor,QPen和QBr ...

  2. 敏捷开发之Scrum扫盲篇(转)

    现在敏捷开发是越来越火了,人人都在谈敏捷,人人都在学习Scrum和XP... 为了不落后于他人,我也开始学习Scrum.今天主要是对我最近阅读的相关资料,根据自己的理解,用自己的语言来描述Scrum中 ...

  3. NOIP2009靶形数独

    题目描述: 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z 博士请教,Z 博士拿出了他最近发明的“ ...

  4. sublime 可能卡的原因

    在重新安装编辑器的时候,配置javascript提示,发现这个插件安装之后,sublime变得非常卡,按照我电脑的性能,同时开着的atom敲代码都不卡.于是把这个插件卸载之后,sublime变得非常流 ...

  5. fio 测试 磁盘I/O: ls -1 /sys/block/sda/queue/ | awk '{cmd="cat "i$0; print i$0; system(cmd) }' i=`pwd`'/'

    小型计算机系统接口(SCSI,Small Computer System Interface) SAS(Serial Attached SCSI,串列SCSI) SCSI 硬盘名称: sd[a-p] ...

  6. python实时得到鼠标的位置

    1.#先下载pyautogui库,打开cmd输入pip install pyautogui,回车 2.代码如下: import os,time import pyautogui as pag try: ...

  7. cookie存值 后取值是string string字符串转对象

    实现方法 // 得到 对象 格式或 json 格式的一个字符串 var str = '{"name":"张根硕","age":"1 ...

  8. 【1】vue/cli 3.0 脚手架 及cube-ui 安装

    安装 Vue CLI 需要 Node.js 8.9 或更高版本 (推荐 8.11.0+).你可以使用 nvm 或 nvm-windows在同一台电脑中管理多个 Node 版本. 检查node版本: $ ...

  9. sap 下载程序

    1: 左下角,直接输入 software centre.  搜索相应程序下载.

  10. Scala集合(一)

    Scala集合的主要特质 Iterator,用来访问集合中所有元素 val coll = ... // 某种Iterable val iter = col.iterator while(iter.ha ...