或许你不知道(2):LinkedList
一,基本的存储结构及数据存取
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的更多相关文章
- 或许你不知道:ArrayList
ArrayList 底层以一个transient 线性数组来存储数据,它提供了无参构造方法,和有参构造方法,用户可以通过有参构造方法来初始化长度.如果不传参数,则默认调用无参构造器,数组默认长度为10 ...
- Python爬取CSDN博客文章
0 url :http://blog.csdn.net/youyou1543724847/article/details/52818339Redis一点基础的东西目录 1.基础底层数据结构 2.win ...
- 一次发现underscore源码bug的经历以及对学术界『拿来主义』的思考
事情是如何发生的 最近干了件事情,发现了 underscore 源码的一个 bug.这件事本身并没有什么可说的,但是过程值得我们深思,记录如下,各位看官仁者见仁智者见智. 平时有浏览园区首页文章的习惯 ...
- 《FreeSWITCH: VoIP实战》:SIP 模块 - mod_sofia
SIP 模块是 FreeSWITCH 的主要模块,所以,值得拿出专门一章来讲解. 在前几章时里,你肯定见过几次 sofia 这个词,只是或许还不知道是什么意思.是这样的,Sofia-SIP 是由诺基亚 ...
- HHVM 是如何提升 PHP 性能的?
背景 HHVM 是 Facebook 开发的高性能 PHP 虚拟机,宣称比官方的快9倍,我很好奇,于是抽空简单了解了一下,并整理出这篇文章,希望能回答清楚两方面的问题: HHVM 到底靠谱么?是否可以 ...
- Css3中的响应式布局的应用
Media Queries直译过来就是“媒体查询”,在我们平时的Web页面中head部分常看到这样的一段代码: <link href="css/reset.css" rel= ...
- [置顶] EasyMock构建单元测试
1. 背景 单元测试作为程序的基本保障.很多时候构建测试场景是一件令人头疼的事.因为之前的单元测试都是内部代码引用的,环境自给自足.开发到了一定程度,你不得不到开始调用外部的接口来完成你的功能.而外部 ...
- Ubuntu常用软件推荐,图文详细说明及下载
抛开Windows,其实在任何一款Linux发行版本中,我们都有超级大量的软件来安装,使用.这次的教程,我就以Ubuntu为例,来给大家推荐一些我认为不错的软件 声明: 1.本文提到的全部软件,都在文 ...
- 为什么Java大数据是最火爆的编程语言?
未来10年将是大数据,人工智能爆发的时代,到时将会有大量的企业需要借助大数据,而Java最大的优势就是它在大数据领域的地位,目前很多的大数据架构都是通过Java来完成的. 在这个Android.iOS ...
随机推荐
- Silverlight动态设置WCF服务Endpoint
2013-02-02 05:57 by jv9, 1763 阅读, 3 评论, 收藏, 编辑 去年12月收到一位朋友的邮件,咨询Silverlight使用WCF服务,应用部署后一直无法访问的问题,通过 ...
- Linux命令学习---目录
一.文件相关命令 1.文件显示 1)tail,head,more,less,cat,nl
- Android图表
最近需要用到Android里面的折现图,因此在这方面也去做了一些调研.总体发现Android对报表的支持还是非常好的.总体上去研究了两个实现方案,一个是利用Android提供的的AChartEngin ...
- 基于Memcached的Session共享问题
把Memcached的key(Guid)写入浏览器的cookie(类比SessionId) 存值: string sessionId = Guid.NewGuid().ToString(); Comm ...
- SQL Server 基础:子查询
1.子查询的概念:子查询就是嵌套在主查询中的查询.子查询可以嵌套在主查询中所有位置,包括SELECT.FROM.WHERE.GROUP BY.HAVING.ORDER BY.2.子查询的分类:2.1按 ...
- C#和.NET版本
1999年,就听说微软公司在研发一种名为“cool”的新开发语言,而具体内幕一直是个谜,直到2000年6月26日微软在奥兰多举行的“职业开发人员技术大会”(PDC 2000)上,这个谜底终于揭晓了,这 ...
- Secondary IP Addressing
Secondary IP Addressing secondary IP addressing. Secondary addressing uses multiple networks or subn ...
- Linux下mysql自动备份
#!/bin/bashDATE=`date +%Y-%m-%d-%H:%M -d -3minute`USER=rootPASSWORD=mayboBACKUP_DIR='/home/mysqlbak/ ...
- SQL中的内连接外连接和交叉连接是什么意思?
内连接又分为等值连接.自然连接和不等连接三种. 外连接分为左外连接(LEFT OUTER JOIN或LEFT JOIN).右外连接(RIGHT OUTER JOIN或RIGHT JOIN)和全外连接( ...
- android开发系列之6*0.9不等于5.4
昨天晚上我们客户端平台上面曝出了一个很奇诡的bug,那就是本来在客户端里面有个商品买6元,但是因为碰巧赶上打9折,这个时候我们很自然的处理就是6*0.9.好吧你以为so easy的事情,其实就出错了, ...