热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

LinkedList底层实现原理

LinkedList的底层实现原理LinkedList底层数据结构为双向链表,链表结构,基于一个个链表节点Node1,InnerClass内部类priv

LinkedList的底层实现原理

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

1,Inner Class 内部类

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

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

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

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


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

}
//public LinkedList(Collection c){
   this();
   addAll(size,c);
}


public boolean addAll(int index,Collection c){
    checkPositionIndex(index);

    Object[] a = c.toArray();
    int numNew = a.length;
    if(numNew == 0)
        return false;
  
    Node pred,succ;//pred 代表要有变化的前节点, succ 代表要变化的后节点
    例:{“good”,"bad","bye","see","to","two","you","me"} 要实现在index = 2 处insert 一个集合,那么Node prev 就是“bad”所在的节点,Node 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 newNode &#61; new Node<>(pred,e,null);
        if(pred &#61;&#61; null)
            first &#61; newNode;
        else
           pred.next &#61; newNode;
       pred &#61; newNode;//为了循环中下一次的赋值&#xff0c;得把pred赋值成当前元素
    }
  
    if(succ &#61;&#61; null){
        last &#61; pred;
    }else{
        pred.next &#61; succ;
        succ.prev &#61; pred;
        //因为pred 在for 循环中插入时候一直有更新&#xff0c;所以这段代码的作用是为了将插入的最后一个节点后变化后的节点连接起来&#xff0c;形成一个新的链表。
    }
}

//找到即将有变化的节点,这个节点永远是变化的后节点
Node node(int index){
    //二分法&#xff0c;如果变化在前半部分&#xff0c;则找出first 如果变化在后半部分&#xff0c;则找出last
    if(index <(size >> 1)){//前半部分
        Node x &#61; first;
        for(int i &#61; 0; i             x &#61; x.next;
        return x;
    }else{
        Node x &#61; last;
        for(int i &#61; size - 1; i>index; i--){
           x &#61; x.prev;
        return x;
        }
    }
}


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

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

 

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

 

4,add
public boolean add(E e){
    linkLast(e);
    return true;
}

void linkLast(E e){

    final Node l &#61; last;
    final Node newNode &#61; new Node<>(l,e,null);
    last &#61; newNode;
    if(l &#61;&#61; null){
    first &#61; newNode;
    }else{
    l.next &#61; newNode;
    }
    size&#43;&#43;;
    modCount&#43;&#43;;
}

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

5 addFirst
public void addFirst(E e){
    linkFirst(e);
}

private void linkFirst(E e){
    Final Node f &#61; first;
    Final Node newNode &#61; new Node(null,e,f);
    first &#61; newNode;

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


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

 

7,removeFirst

public E removeFirst(E e){
    final Node f &#61; first;
    if(f &#61;&#61; null)
        throw new NoSuchElementException();

    return unLinkFirst(f);
}

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

    size--;
    modCount&#43;&#43;;

   return element;
}

 

8,removeLast

public E removeLast(E e){
    final Node l &#61; last;
    if(last &#61;&#61; null)
        throw new NoSuchElementException();
    return unLinkLast(l);
}

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

    if(prev &#61;&#61; null)
        first &#61; prev;
    else
        prev.next &#61; null;

    size--;
    modeCount&#43;&#43;:
    return element;
}

9,getFirst

public E getFirst(){
    fianl Node f &#61; first;
    if(f &#61;&#61; null)
        throw new NoSuchElementException();
    return f.item;
}

10,getLast

public E getLast(){
    final Node l &#61; last;
    if(l &#61;&#61; null)
        throw new NoSuchElementException();
    return l.item;
}

 11,查询

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

转:https://www.cnblogs.com/pickKnow/p/9199247.html



推荐阅读
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
author-avatar
YON永世
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有