先摆上JDK1.8中hashMap的类注释;我翻译了一下

/**
* Doubly-linked list implementation of the {@code List} and {@code Deque}
* interfaces. Implements all optional list operations, and permits all
* elements (including {@code null}).
* 双向链表实现了List和Deque接口。实现了List所有的操作,双向链表允许所有元素,包括null
*
* <p>All of the operations perform as could be expected for a doubly-linked
* list. Operations that index into the list will traverse the list from
* the beginning or the end, whichever is closer to the specified index.
* 对于LinkedList所有的操作都是可以被预期的。操作LinkedList将会遍历LinkedList的指针.
* 解读:通过set(i,e),get(i)访问LinkedList的元素时,要遍历指针,如果i>LinkedList容量的一半,
* 就从尾部开始遍历.
*
* <p><strong>Note that this implementation is not synchronized.</strong>
* If multiple threads access a linked list concurrently, and at least
* one of the threads modifies the list structurally, it <i>must</i> be
* synchronized externally. (A structural modification is any operation
* that adds or deletes one or more elements; merely setting the value of
* an element is not a structural modification.) This is typically
* accomplished by synchronizing on some object that naturally
* encapsulates the list.
* 注意,LinkedList是线程不同步的.如果多线程同时访问LinkedList,此时如果有一个线程修改LinkedList结构,
* 那么就必须在外层进行同步操作处理(这里的修改结构包括添加元素,删除元素)。
* 解读:ArrayList同样有此特性.
*
* If no such object exists, the list should be "wrapped" using the
* {@link Collections#synchronizedList Collections.synchronizedList}
* method. This is best done at creation time, to prevent accidental
* unsynchronized access to the list:<pre>
* List list = Collections.synchronizedList(new LinkedList(...));</pre>
* 考虑线程同步问题,可以用Collections.synchronizedList替代LindedList
*
* <p>The iterators returned by this class's {@code iterator} and
* {@code listIterator} methods are <i>fail-fast</i>: if the list is
* structurally modified at any time after the iterator is created, in
* any way except through the Iterator's own {@code remove} or
* {@code add} methods, the iterator will throw a {@link
* ConcurrentModificationException}. Thus, in the face of concurrent
* modification, the iterator fails quickly and cleanly, rather than
* risking arbitrary, non-deterministic behavior at an undetermined
* time in the future.
* 在迭代一个LinkedList时,任何修改LinkedList的操作,迭代器都会终止,并抛出
* ConcurrentModificationException异常.
*
* <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
* as it is, generally speaking, impossible to make any hard guarantees in the
* presence of unsynchronized concurrent modification. Fail-fast iterators
* throw {@code ConcurrentModificationException} on a best-effort basis.
* Therefore, it would be wrong to write a program that depended on this
* exception for its correctness: <i>the fail-fast behavior of iterators
* should be used only to detect bugs.</i>
* 快速失败机制,是一种错误检测机制。它只能被用来检测错误,因为JDK并不保证fail-fast机制一定会发生.
* 参考我的博客 ”Iterator fail-fast“
* 
* @author Josh Bloch
* @see List
* @see ArrayList
* @since 1.2
* @param <E> the type of elements held in this collection
*/
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable

总结

1.  LinkedList是基于链表结构实现,所以在类中包含了first和last两个指针(Node)。Node中包含了上一个节点和下一个节点的引用,这样就构成了双向的链表。每个Node只能      

  知道自己的前一个节点和后一个节点,但对于链表来说,这已经足够了

  在此看一下LinkedList的数据结构,立体感受一下这个特性

所以LinkedList插入和删除元素效率很高,比ArrayList高。通过set(i,e),get(i)访问效率低,因为要遍历指针,如果i>size/2,那么就从尾部开始遍历。

翻阅get(i),set(i,E)的源码

 /**
* Replaces the element at the specified position in this list with the
* specified element.
*
* @param index index of the element to replace
* @param element element to be stored at the specified position
* @return the element previously at the specified position
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E set(int index, E element) {
checkElementIndex(index);
Node<E> x = node(index);
E oldVal = x.item;
x.item = element;
return oldVal;
} /**
* Returns the element at the specified position in this list.
*
* @param index index of the element to return
* @return the element at the specified position in this list
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E get(int index) {
checkElementIndex(index);
return node(index).item;
} /**
* Returns the (non-null) Node at the specified element index.
*/
Node<E> node(int index) {
// assert isElementIndex(index); if (index < (size >> 1)) {
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}

很明显,在进行set和get操作时,并不是每次都从头部开始遍历指针的,而是调用了node(int index)这个方法,就是用来判断当前index的大致位置,如果i<(size>>1)也就是i<size/2,那么从first开始遍历,否则从last开始遍历。此时set,get操作的时间复杂度也就由O(n)变成了O(n/2)

2. 链表没有容量限制,但是双向链表本身使用了更多的空间.每插入一个元素都要构造一个Node对象

3. LinkedList线程不同步,采用fail-fast机制

LinkedList 学习笔记的更多相关文章

  1. [Java] LinkedList / Queue - 源代码学习笔记

    简单地画了下 LinkedList 的继承关系,如下图.只是画了关注的部分,并不是完整的关系图.本博文涉及的是 Queue, Deque, LinkedList 的源代码阅读笔记.关于 List 接口 ...

  2. 《Java学习笔记(第8版)》学习指导

    <Java学习笔记(第8版)>学习指导 目录 图书简况 学习指导 第一章 Java平台概论 第二章 从JDK到IDE 第三章 基础语法 第四章 认识对象 第五章 对象封装 第六章 继承与多 ...

  3. Redis学习笔记一:数据结构与对象

    1. String(SDS) Redis使用自定义的一种字符串结构SDS来作为字符串的表示. 127.0.0.1:6379> set name liushijie OK 在如上操作中,name( ...

  4. 20145330第五周《Java学习笔记》

    20145330第五周<Java学习笔记> 这一周又是紧张的一周. 语法与继承架构 Java中所有错误都会打包为对象可以尝试try.catch代表错误的对象后做一些处理. 使用try.ca ...

  5. Android(java)学习笔记267:Android线程池形态

    1. 线程池简介  多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力.     假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...

  6. 黑马程序员-C#学习笔记(二)

    ---------------------- ASP.Net+Android+IOS开发..Net培训.期待与您交流! ---------------------- - C# 学习笔记 一.变量与表达 ...

  7. Web Service学习笔记(webservice、soap、wsdl、jws详细分析)

    Web Service概述 Web Service的定义 W3C组织对其的定义如下,它是一个软件系统,为了支持跨网络的机器间相互操作交互而设计.Web Service服务通常被定义为一组模块化的API ...

  8. Web Service学习笔记

    Web Service概述 Web Service的定义 W3C组织对其的定义如下,它是一个软件系统,为了支持跨网络的机器间相互操作交互而设计.Web Service服务通常被定义为一组模块化的API ...

  9. [Java] List / ArrayList - 源代码学习笔记

    在阅读 List / ArrayList 源代码过程中,做了下面的笔记. LinkedList 的笔记较多,放到了另一篇博文 LinkedList / Queue- 源代码学习笔记 List List ...

随机推荐

  1. 入坑系列之HAProxy负载均衡

    在大型系统设计中用代理在负载均衡是最常见的一种方式,而相对靠谱的解决方案中Nginx.HAProxy.LVS.F5在各大场中用得比较普遍,各有各的优势和使用场景,由于本次要使用到TCP,因此Nginx ...

  2. AVFoundation自定义录制视频

    #import <AVFoundation/AVFoundation.h> #import <AssetsLibrary/AssetsLibrary.h> @interface ...

  3. 快速上手UIBezierPath

    UIBezierPath主要用来绘制矢量图形,它是基于Core Graphics对CGPathRef数据类型和path绘图属性的一个封装,所以是需要图形上下文的(CGContextRef),所以一般U ...

  4. RSA密码体制

    公钥算法的基本数论知识 公钥密码学中大部分引用了数论的成果,所以必要在介绍RSA密码体制之前,详细介绍一下所使用的几个数论的知识点 欧几里得算法 欧几里得算法主要是解决最大公约数问题,记两个正整数\( ...

  5. 【转】请求处理机制其二:Django中间件的解析

    Middleware 开始工作了 get_response 做的第一件事就是遍历处理器的 _request_middleware 实例变量并调用其中的每一个方法,传入 HttpRequest 的实例作 ...

  6. 存储结构与邻接矩阵,深度优先和广度优先遍历及Java实现

    如果看完本篇博客任有不明白的地方,可以去看一下<大话数据结构>的7.4以及7.5,讲得比较易懂,不过是用C实现 下面内容来自segmentfault 存储结构 要存储一个图,我们知道图既有 ...

  7. SQL Server中的Merge关键字 更新表数据

    简介 Merge关键字是一个神奇的DML关键字.它在SQL Server 2008被引入,它能将Insert,Update,Delete简单的并为一句.MSDN对于Merge的解释非常的短小精悍:”根 ...

  8. Android开发之启动模式的深入理解

    standard(标准模式): 当用ApplicationContext去启动standard模式时会报错,是因为非Activity类型的Context没有所谓的任务栈, 所以需要为待启动的Activ ...

  9. python编码问题之\"encode\"&\"decode\"

    python encode decode 编码 decode的作用是将其他编码的字符串转换成unicode编码,如str1.decode('gb2312'),表示将gb2312编码的字符串str1转换 ...

  10. js中的this关键字,setTimeout(),setInterval()的执行过程

    var test1 = { name: 'windseek1', showname: function () { console.log(this.name); } } var test2 = { n ...