或许你不知道(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 ...
随机推荐
- 快速清理Visual Studio起始页最近打开项目
清除vs2008起始页最近打开项目 第一种:最简单的方式: 把以下内容保存为.bat批处理文件 @echo off@REG Delete HKCU\Software\Microsoft\VisualS ...
- 用户 'sa' 登录失败。 (Microsoft SQL Server,错误: 18456)
今天登陆数据库的时候,却忽然登陆了不了,并且提示了这样的错: 解决方法: 1.用Windows身份登录数据库 2.安全性==>登录名==>双击sa 3.重设密码 4.状态==>登录: ...
- 网页热力图 heatmap js
HBuilder +js 实现网页热力图 废话不多说,上代码 <!DOCTYPE html> <html> <head> <title>111</ ...
- CentOS用户权限管理--su与sudo
Linux权限管理--su与sudo 1.su用来切换登录的用户,比如当前用户为chen,可以用su zhu,并输入用户zhu的登录密码,就可以切换到用户zhu.如果一个普通用户想切换到root用户, ...
- Flex 4.0及4.6发布的网络应用在内网内会访问很慢的解决方案
Flex 4.x 开发的程序部署在外网在能访问到www.adobe.com的时能够很快加载完成,但是部署在本地局域网,不能访问外网的服务器上,用浏览器访问应用需要加载几分钟的时间,这种等待时间客户几乎 ...
- 统计图表--第三方开源--MPAndroidChart(一)
效果图1: 效果图2: MPAndroidChart是在Android平台上开源的第三方统计图表库,可以绘制样式复杂.丰富的各种统计图表,如一般常见的折线图.饼状图.柱状图.散点图.金融股票中使用的的 ...
- IntentService 串联 按顺序执行(此次任务执行完才执行下一个任务)
IntentService与Service的最大区别就是前者依次执行,执行完当前任务才执行下一个任务,后者并发执行 在IntentService里面不写onCreate方法 MainActivity: ...
- JDBC基础一
JDBC:java database connectivity SUN公司提供的一套操作数据库的标准规范. JDBC与数据库驱动的关系:接口与实现的关系. JDBC规范(掌握四个核心对象): Driv ...
- DM9000网卡的基本工作原理
MAC:主要负责数据帧的创建,数据差错,检查,传送控制等. PHY:物理接口收发器,当收到MAC过来的数据时,它会加上校验码,然后按照物理层的规则进行数据编码,再发送到传输介质上,接收过程则相反. M ...
- 说说用C语言求根的那些事儿
C语言--求根:计算机只识别0和1,那么问题来了,作为计算工具如何解决数学问题?其实,计算机是死东西,都是程序员用计算机的的思维去加数学公式计算数学题的.听起来好高端的样子,其实啊,也就那么回事儿, ...