`
yuwenlin2008
  • 浏览: 125200 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

LinkedList源码解析(Jdk6)

阅读更多

Java的LinkedList是基于双向链表实现的List集合类。它的特点有:

1.没有容量限制。

2.添加,删除元素比较快;检索元素较慢(较ArrayList)。

3.可能实现为队列,栈

4.线程不安全

下面来看其源码实现:

1.类定义

 

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable

LinkedList继承自AbstractSequentialList,AbstractSequentialList继承AbstractList的大部分功能,实现List,Deque接口,Deque定义了双端队列的一些个方法。可克隆,可被序列化。

2.属性定义

private transient Entry<E> header = new Entry<E>(null, null, null);
private transient int size = 0;

size:集合的大小。

Entry:LinkedList存储数据的地方,就是靠它实现双向链接,每new一个新的ArrayList实例,就会创建一个空的header,它表示链表的头,来看它的实现:

private static class Entry<E> {
	E element;
	Entry<E> next;
	Entry<E> previous;

	Entry(E element, Entry<E> next, Entry<E> previous) {
	    this.element = element;
	    this.next = next;
	    this.previous = previous;
	}
    }

a.首先它支持泛型

b.属性element用来存储我们实际的值,可以是普通类型,也可以引用类型。

c.属性next和previous实现双向链接的下一个节点,上一个节点

3.构造方法,来看我们new LinkedList()都干了什么

public LinkedList() {
        header.next = header.previous = header;
    }

这是无参构造方法,因为上面讲了,每次new都会创建一个空的header节点,那构造方法做的就是它的下一个节点和上一个节点,这里都是指向自身,从而形成一个闭环。

4.add(),我们看添加元素,它是怎么实现的

public boolean add(E e) {
	addBefore(e, header);
        return true;
    }

private Entry<E> addBefore(E e, Entry<E> entry) {
	Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);
	newEntry.previous.next = newEntry;
	newEntry.next.previous = newEntry;
	size++;
	modCount++;
	return newEntry;
    }

它调用了addBefore()方法,在之前插入,那就是每次在header之前插入了,看它实现:

a.new一个新的Entry节点,element为我们添加的元素对象,next节点为header,上一个节点为entry.previous=header.previous=header,即下一个节点和上一个节点都为header。

b.newEntry.previous.next=header.next=newEntry,即将header的下一个节点设置为新创建的Entry节点。

c.newEntry.next.previous=header.previous = newEntry,即将header的上一个节点设置为新创建的Entry节点。这时新插入的newEntry节点便和header形成一个新的闭环。LinkedList就是这样来插入新的元素。

d.size++,LinkedList大小加1。

e.modCount++,修改次数加1。

转一张图过来,其实我自己也用笔画出来了。

理解这个add()方法,能自己画出这张图,LinkedList的实现原理就搞明白了,后面都是它的应用。

5.get()方法

public E get(int index) {
        return entry(index).element;
    }

private Entry<E> entry(int index) {
        if (index < 0 || index >= size)
            throw new IndexOutOfBoundsException("Index: "+index+
                                                ", Size: "+size);
        Entry<E> e = header;
        if (index < (size >> 1)) {
            for (int i = 0; i <= index; i++)
                e = e.next;
        } else {
            for (int i = size; i > index; i--)
                e = e.previous;
        }
        return e;
    }

它调用entry(),size >> 1这个是右位运算,意思是size除以2^1,左移就是乘以2^1,所以这里检索的方法是用被检索的索引值与LinkedList集体大小的一半比较,小于它,从前面开始找,大于它,则从后面开始找。所以它的检索效率没有ArrayList高,但是它插入,删除高效啊。

6.remove()

public E remove(int index) {
        return remove(entry(index));
    }

private E remove(Entry<E> e) {
	if (e == header)
	    throw new NoSuchElementException();

        E result = e.element;
	e.previous.next = e.next;
	e.next.previous = e.previous;
        e.next = e.previous = null;
        e.element = null;
	size--;
	modCount++;
        return result;
    }

a.首先找到这个节点,然后调用remove()方法,

b.把它的上一个节点的next指向它的下一个节点,下一个节点的previous指向它的上一个节点,有点绕,但是好理解, 

c.把它自己的下一个节点和上一个节点指向都设置为null,

d.把它的值设置为null

e.修改次数加1,并返回该元素的值。

其它方法还有很多,但理解上面这些,LinkedList就是没问题了

据其它网友的总结:

1.对LinkedList的遍历采用新特性的for循环,效率较高,

for (Integer integ:list) 
    ; 

其次是迭代,千万不要用随机访问,那是ArrayList的强项。

 

参考:

http://www.cnblogs.com/hzmark/archive/2012/12/25/LinkedList.html

http://www.cnblogs.com/skywang12345/p/3308807.html  

 

分享到:
评论

相关推荐

    源码解析jdk7.0集合:LinkedList的底层实现原理.pdf

    源码解析jdk7.0集合:LinkedList的底层实现原理.pdf

    Jdk1.6 Collections Framework源码解析(2)-LinkedList

    NULL 博文链接:https://brokendreams.iteye.com/blog/1916061

    Java基于JDK 1.8的LinkedList源码详析

    主要给大家介绍了关于Java基于JDK 1.8的LinkedList源码的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    JDK-s-source-parser:解析jdk源码-源码解析

    JDK-s-source-parser ## Java的JDK原始解析###完成部分Collection / ArrayList.java由:me 2016-3-31 Collection / LinkedList.java发布者:CBQ 2016-4-4

    java8源码-csn-list:ArrayList、LinkedList、Vector、Stack源码分析

    List相关实现类的源码解析(JDK1.8) 2018.9.22- List的架构图 ArrayList 继承关系: ArrayList -&gt; AbstractList 实现 List接口 ArrayList 是一个数组队列,相当于 动态数组。与Java中的数组相比,它的容量能动态...

    Java JDK实例宝典

    全部代码出自电子工业出版社夏先波的《Java JDK实例宝典》一书,本书以J2SE 5.0为开发环境,选取Java应用的典型实例,循序渐进地介绍了Java语言的各种开发方法和技巧,实例代码注释详细规范,思路清晰。 第1章 ...

    java基础案例与开发详解案例源码全

    2.3.5 常见错误解析24 2.4 Java类库组织结构和文档27 2.5 Java虚拟机简介28 2.6 Java技术两种核心运行机制29 2.7 上机练习30 第3章 3.1 变量32 3.1.1 什么是变量32 3.1.2 为什么需要变量32 3.1.3 变量的声明和赋值33...

    JAVA 范例大全 光盘 资源

    实例1 下载、安装并配置JDK 1 实例2 第一个Java程序 3 实例3 在Eclipse中创建第一个Java程序 4 常见问题 javac不是内部或者外部命令 6 常见问题 找不到类文件 6 常见问题 语法错误 7 第2章 Java基础语法 9 ...

    汪文君高并发编程实战视频资源全集

    │ 高并发编程第二阶段46讲、ClassLoader链接阶段(验证,准备,解析)过程详细介绍.mp4 │ 高并发编程第二阶段47讲、ClassLoader初始化阶段详细介绍clinit.mp4 │ 高并发编程第二阶段48讲、JVM内置三大类加载器...

    汪文君高并发编程实战视频资源下载.txt

    │ 高并发编程第二阶段46讲、ClassLoader链接阶段(验证,准备,解析)过程详细介绍.mp4 │ 高并发编程第二阶段47讲、ClassLoader初始化阶段详细介绍clinit.mp4 │ 高并发编程第二阶段48讲、JVM内置三大类加载器...

    java面试题

    4. 说出ArrayList,Vector,LinkedList的存储性能和特性 8 5. EJB是基于哪些技术实现的?并说出SessionBean和EntityBean的区别,StatefulBean和StatelessBean的区别。 9 6. Collection 和 Collections的区别。 9 7. &...

    超级有影响力霸气的Java面试题大全文档

    6、int 和 Integer 有什么区别  Java 提供两种不同的类型:引用类型和原始类型(或内置类型)。Int是java的原始数据类型,Integer是java为int提供的封装类。Java为每个原始类型提供了封装类。 原始类型 封装类 ...

    java 面试题 总结

    6、说出Servlet的生命周期,并说出Servlet和CGI的区别。 Servlet被服务器实例化后,容器运行其init方法,请求到达时运行其service方法,service方法自动派遣运行与请求对应的doXXX方法(doGet,doPost)等,当服务器...

Global site tag (gtag.js) - Google Analytics