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

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. Centos6.5(final)安装gcc和g++,python以及导致问题的解决方法

    安装gcc:yum install gcc  安装g++:yum install gcc-c++ 安装python: centos默认是2.6的版本, 下载python ,我下载的是2.7.10. 1 ...

  2. SQL中查看数据库各表的大小

    SQL中查看数据库各表的大小 编写人:CC阿爸 2014-6-17 在日常SQL数据库的操作中,如何快速的查询数据库中各表中数据的大小. 以下有两种方法供参考: 第一种: create table # ...

  3. pjax 历史管理 jQuery.History.js

    更新 http://www.bootcdn.cn/jquery.pjax/ 简介 pjax是一个jQuery插件,使用ajax和pushState技术提供快速的浏览体验与真正的永久链接.网页标题.以及 ...

  4. 一款jQuery满屏自适应焦点图切换特效

    一款jQuery满屏自适应焦点图切换特效 ,自适应当前浏览器的宽度,可以作为网站整个大背景的却换效果,很不错的一款不jquery特效. 兼容性没的说直接秒杀了IE6.适用浏览器:IE6.IE7.IE8 ...

  5. Ubuntu通过APT配置开发环境

    apt-get install vim apt-get install ssh apt-get install apache2 apt-get install redis-server apt-get ...

  6. PHP file_get_contents于curl性能效率比较

    说明大部分内容整理来源于网络,期待你的补充.及不当之处的纠正: 1)fopen/file_get_contents 每次请求远程URL中的数据都会重新做DNS查询,并不对DNS信息进行缓存.但是CUR ...

  7. 3)Java容器

    3)Java容器   Java的集合框架核心主要有三种:List.Set和Map.这里的 Collection.List.Set和Map都是接口(Interface). List lst = new ...

  8. Win7更改默认打开方式失败

    问题描述:选定某个给定文件,然后鼠标右键选择打开方式,在浏览后选到自己期望使用的应用程序,然后单击确定后,却发现没有任何效果.原文件仍然保持原来的打开方式. 问题原因:更好程序或者升级程序时安装路径发 ...

  9. 谈谈final、finally、finalize的区别

    1.final:如果一个类被final修饰,意味着该类不能派生出新的子类,不能作为父类被继承.因此一个类不能被声明为abstract,又被声明为final.将变量或方法声明为final.可以保证他们在 ...

  10. STM32F0xx_ADC采集电压配置详细过程

    前言 关于ADC这一块的功能基本上也算是CortexM芯片的标配了.ST的每一块芯片都有这个功能,只是说因型号不同,通道数.位数等有所不同.STM8的芯片大多数都是10的,也就是说分辨率可达到:参考电 ...