一,基本的存储结构及数据存取

LinkedList与ArrayList同属List的范畴,ArrayList实现了RandomAccess接口,通过索引随机访问效率较高,而LinkedList提供了直接访问首属的方法,由于链表的不规则性,要找到LinkedList里面的某个元素相对是比较困难的,但只要找它这个元素要对它进行更新操作是比较高效的。这种高效只通过LinkedList的构造方法就可见一斑。

LinkedList用一个内部类Entry来保存数据。Entry有三个重要属性,element,下一元素next,上一元素previous.从构造方法中可以看出,当前的元素即初始化第一个元素

为header,它的下一元素等于它的上一元素等于本身,也就是当前只有一个header,处于初始化状态为空。它奠定了LinkedList存取元素的一个基本特征,每添加一个元素随机分配位置,但必然要指明它相邻位置的元素,如果需要更新,只需要通过next,previous两个属性重新指定到新的元素,即可完成。而不需要像ArrayList一样重新排列复制所有元素。

看一下LinkedList是怎样添加元素的:

首先,调用这两个方法,都会去调用addBefore()方法,然后传入元素和位置,如果是addFirst()则位置为header.next,如果是addLast()则位置为header,从字面上来理解header是头部的意思,怎么会在addLast()时把它当做位置呢?

别急,我们先来看一下addBefor()的实现,如图:

可以清楚的看到,当调用addLast()时,传过来的位置header通过addBefore()调用Entry的构造方法,它指向的是next,也就是说,当前我要加的元素为element,它的next即下一个元素为header即第一个元素,那么它必然就是最后一个元素喽!但是新的问题出来了,如果是addFirst()呢,它传过来的位置为位置为header.next,同样会指向下一个,把header.next作为当前元素,那么header呢?Header在哪里?那它岂不是没有存储东西?通过观察刚开始的构造方法,实例化一个LinkedList的时候,header确实为空,这时长度size为0,然后在对LinkedList进行存取操作的时候,都没有直接对header进行操作。这可以通过Entry类的remove(用户不可以直接调用)得到佐证。如果你要对header进行删除,会报NoSuchElementException()异常,表明根本就没有这个节点元素。如图:

那么LinkedList为什么要设计这么一个header呢?

我的理解有两点。1,LinkedList底层以链表存储数据,不同于数组,在初始化的时候用户得到一个LinkedList的实例,在这之前,它必须得向内存要空间啊,数组由于可以分配连续的空间,因而可以申请预留空间,但链表由于随机的存储方式(总感觉这种表述不科学啊),如果申请太多预留空间造成较大浪费,所以只能一个,即是给header。2,header不存储数据,也不能算是浪费,因为它虽然没数据但通过next和previous相当于前后的指针,为后进的数据提供安身之所,这是LinkedList存储或者叫算法的体现。

事实上,本人觉得LinkedList最精妙最精华的部分就在于这个addBefor()这部分代码。

前边讲到,既然从一开始的header都有指针,那么LinkedList不管存储多少数据,它必然有一个首尾结合类似于圆的指针链。那么它的往哪存放呢?从代码中可以看到,它实际上是在首或者尾(默认add()为尾)的地方,先打破前后的指针,插入这个位置,然后再通过next和previous指向两旁。Remove()方法,与此类似,先打破被删除的元素指针,然后把它设为NULL.

二,关于modCount与Deque<E>

上篇讲过,modCount保存存储集合被修改更新的次数。集合存储数据的载体Entry对象修饰符为transient,它不属于序列化的一部分。在集合迭代的时候需要用modCount来保证此时外部或其它线程不能对它进行更新修改。

LinkedList实现了Deque接口,此接口又继承自Queue接口。对Queue不熟悉,队列的特性是先进先出。LinkedList中提供一些很少使用(至少本人)的方法都要是基于队列的民,如:peek(),poll(),offer()等.

有意思有一个小细节是,当我们基于面向对象多态的思想定义一个LinkedList集合,List<String> link= new LinkedList<String>();发现无法调用上面提到的这些方法,必须使用LinkedList<String> link = new LinkedList<String>()才可以。

先进先出:

或许你不知道(2):LinkedList的更多相关文章

  1. 或许你不知道:ArrayList

    ArrayList 底层以一个transient 线性数组来存储数据,它提供了无参构造方法,和有参构造方法,用户可以通过有参构造方法来初始化长度.如果不传参数,则默认调用无参构造器,数组默认长度为10 ...

  2. Python爬取CSDN博客文章

    0 url :http://blog.csdn.net/youyou1543724847/article/details/52818339Redis一点基础的东西目录 1.基础底层数据结构 2.win ...

  3. 一次发现underscore源码bug的经历以及对学术界『拿来主义』的思考

    事情是如何发生的 最近干了件事情,发现了 underscore 源码的一个 bug.这件事本身并没有什么可说的,但是过程值得我们深思,记录如下,各位看官仁者见仁智者见智. 平时有浏览园区首页文章的习惯 ...

  4. 《FreeSWITCH: VoIP实战》:SIP 模块 - mod_sofia

    SIP 模块是 FreeSWITCH 的主要模块,所以,值得拿出专门一章来讲解. 在前几章时里,你肯定见过几次 sofia 这个词,只是或许还不知道是什么意思.是这样的,Sofia-SIP 是由诺基亚 ...

  5. HHVM 是如何提升 PHP 性能的?

    背景 HHVM 是 Facebook 开发的高性能 PHP 虚拟机,宣称比官方的快9倍,我很好奇,于是抽空简单了解了一下,并整理出这篇文章,希望能回答清楚两方面的问题: HHVM 到底靠谱么?是否可以 ...

  6. Css3中的响应式布局的应用

    Media Queries直译过来就是“媒体查询”,在我们平时的Web页面中head部分常看到这样的一段代码: <link href="css/reset.css" rel= ...

  7. [置顶] EasyMock构建单元测试

    1. 背景 单元测试作为程序的基本保障.很多时候构建测试场景是一件令人头疼的事.因为之前的单元测试都是内部代码引用的,环境自给自足.开发到了一定程度,你不得不到开始调用外部的接口来完成你的功能.而外部 ...

  8. Ubuntu常用软件推荐,图文详细说明及下载

    抛开Windows,其实在任何一款Linux发行版本中,我们都有超级大量的软件来安装,使用.这次的教程,我就以Ubuntu为例,来给大家推荐一些我认为不错的软件 声明: 1.本文提到的全部软件,都在文 ...

  9. 为什么Java大数据是最火爆的编程语言?

    未来10年将是大数据,人工智能爆发的时代,到时将会有大量的企业需要借助大数据,而Java最大的优势就是它在大数据领域的地位,目前很多的大数据架构都是通过Java来完成的. 在这个Android.iOS ...

随机推荐

  1. 银行ATM机工作流程模拟编程(代码)

    #include<stdio.h>#include<stdlib.h>#include <conio.h>#include <string.h> voi ...

  2. MBR解析

    先推广一下QQ群:61618925.欢迎各位爱好编程的朋友加入. 一.程序界面 二.关键部分代码: 1.数据结构定义 #define MBRSIZE 512 #define BOOTRECORDSIZ ...

  3. zencart用chrome无法登录后台

    再本地安装完zencart后,可以使用ie和Firefox登录网站后台,但是使用chrome登录时,页面闪一下,然后又跳转到登录页面. 按如下设置可以解决该问题: 中文版:商店设置->Sessi ...

  4. redmine添加自定义属性

    使用redmine创建问题的时候,可能会发现没有我们需要的属性,这时候我们可以添加自定义的属性. 以添加满意度属性为例: 1.进入redmine管理界面,选择自定义属性 2.选择问题下面的新建自定义属 ...

  5. oracle中=>是什么意思

    => 是 Oracle 中调用 存储过程的时候, 指定 参数名进行调用.一般是, 某些参数有默认值的时候,你需要跳过某些参数来进行调用.下面是具体的例子. 参数的默认值SQL> CREAT ...

  6. PHP搜索MYSQL数据库加分页浏览小结

    PHP搜索加分页浏览小结: 1 分页后再做搜索 2 这里对于url的拼接,以及模糊查询,搜索时候的显示添加,SQL语句的拼接 3 对于页面传递过来的超级链接的变量,如果不存在就要设置,对于可能抛出异常 ...

  7. Ksoap2 获取webservice返回值的getResponse() 出现的问题

    今天写了一个判断记录重复的webservcie 返回布尔类型 // 判断序列号在数据库是否重复 public static boolean isSerialNumExist(String serial ...

  8. git传输协议原理

    git精神:distributed-is-the-new-centralized 转自:http://git-scm.com/book/zh/v1/Git-%E5%86%85%E9%83%A8%E5% ...

  9. ED/EP系列4《圈存指令》

    1. 圈存交易 通过圈存交易,持卡人可将其在银行相应账户上的资金划入电子存折或电子钱包中. 特点: 1)--必须在金融终端上联机进行; 2)--必须提交个人识别码(PIN) 步骤: 1) --终端: ...

  10. Maven系列--pom.xml 配置详解

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...