一.LinkedList的内部数据结构

  LinkedList底层是一个链表的数据结构,采用的是双向链表,基本的Node数据结构代码如下:

private static class Node<E> {
E item; //节点放置的元素
Node<E> next; //下一节点
Node<E> prev; //上一结点 Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}

二.LinkedList的结点的常用操作

  在LinkedList实现List接口的一系列方法的时候,底层是通过一系列结点操作,完成对于LinkedList的方法的实现,操作代码如下:

    /**
* 将一个元素链接到链表的开头
*/
private void linkFirst(E e) {
final Node<E> f = first;
final Node<E> newNode = new Node<>(null, e, f);
first = newNode;
if (f == null)
last = newNode;
else
f.prev = newNode;
size++;
modCount++;
} /**
* 将元素e链接到链表的末端
*/
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
} /**
* 将一个元素链接到指定结点的前面
*/
void linkBefore(E e, Node<E> succ) {
// assert succ != null;
final Node<E> pred = succ.prev;
final Node<E> newNode = new Node<>(pred, e, succ);
succ.prev = newNode;
if (pred == null)
first = newNode;
else
pred.next = newNode;
size++;
modCount++;
} /**
* 将一个first结点解除关联
*/
private E unlinkFirst(Node<E> f) {
final E element = f.item;
final Node<E> next = f.next;
f.item = null;
f.next = null; // help GC
first = next;
if (next == null)
last = null;
else
next.prev = null;
size--;
modCount++;
return element;
} /**
* 将一个last结点解除关联
*/
private E unlinkLast(Node<E> l) {
final E element = l.item;
final Node<E> prev = l.prev;
l.item = null;
l.prev = null; // help GC
last = prev;
if (prev == null)
first = null;
else
prev.next = null;
size--;
modCount++;
return element;
} /**
* 将一个结点x解除链接
*/
E unlink(Node<E> x) {
final E element = x.item;
final Node<E> next = x.next;
final Node<E> prev = x.prev; if (prev == null) {
first = next;
} else {
prev.next = next;
x.prev = null;
} if (next == null) {
last = prev;
} else {
next.prev = prev;
x.next = null;
} x.item = null;
size--;
modCount++;
return element;
}

三.LinkedList的addAll方法

  插入一个Collection类型的元素的时候,需要先将Collection元素转化为数组类型的元素,然后对于数组中的每一个元素进行遍历,建立一系列结点,并将结点相互连接,然后与原来的结点相互连接.

public boolean addAll(int index, Collection<? extends E> c) {
checkPositionIndex(index);
Object[] a = c.toArray();
int numNew = a.length;
if (numNew == 0)
return false; Node<E> pred, succ;
if (index == size) { //表示在链表末尾添加
succ = null;
pred = last;
} else { //在链表中间添加
succ = node(index);//获取在当前索引位置的元素
pred = succ.prev;//pred--记录当前索引位置的元素的前面的一个元素
} for (Object o : a) {
@SuppressWarnings("unchecked") E e = (E) o;
Node<E> newNode = new Node<>(pred, e, null); //在当前索引位置的元素前面添加元素
if (pred == null) //前面没有元素,说明插入的节点是链表的第一个元素
first = newNode;
else //前面节点的next指向当前节点
pred.next = newNode;
pred = newNode; //pred指向当前节点为下一次赋值做准备
} if (succ == null) { //插入前,索引处没有元素
last = pred;
} else {
pred.next = succ;
succ.prev = pred;
} size += numNew;
modCount++;
return true;
}

四.remove操作

  remove操作通过对于链表结点进行遍历,如果结点的元素等于参数的元素,则调用unlink方法,将结点的关系解除.

public boolean remove(Object o) {
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null) {
unlink(x);
return true;
}
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}

五.clear方法

  通过对于链表的所有的元素进行遍历,并且将遍历到的元素的所有属性设为null,交给垃圾回收器处理.

public void clear() {
for (Node<E> x = first; x != null; ) {
Node<E> next = x.next;
x.item = null;
x.next = null;
x.prev = null;
x = next;
}
first = last = null;
size = 0;
modCount++;
}

六.get方法

  get方法是LinkedList获取某一索引处的元素的方法,由于链表的数据结构查询比较慢,因此通常不推荐对于LinkedList类型的数据结构调用一系列get方法.但是LinkedList数据结构本身对于get方法进行了优化,当索引大于中间索引的时候,从最后一个元素开始查询.当索引小于中间索引的时候,从第一个元素开始查询.

 public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
Node<E> node(int 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;
}
}

Java源码初学_LinkedList的更多相关文章

  1. Java源码初学_AbstractList&AbstractCollection

    一.AbstractCollection抽象类:(提供了Collection接口的骨干实现,以减少实现接口所需要的工作) 1.contains方法 contains方法,通过迭代器对于列表的每一个元素 ...

  2. Java源码初学_HashSet&LinkedHashSet

    一.概述 HashSet是建立在HashMap的基础上的,其内部存在指向一个HashMap对象的引用,操作HashSet实际上就是操作HashMap,而HashMap中所有键的值都指向一个叫做Dumm ...

  3. Java源码初学_LinkedHashMap

    一.概述: LinkedHashMap是HashMap的子类,它的基本操作与HashMap相同,与之不同的是,它可以实现按照插入顺序进行排序.也可以通过在构造函数中指定参数,按照访问顺序排序(Link ...

  4. Java源码初学_HashMap

    一.概念 HashMap的实例有两个参数影响其性能:初始容量和加载因子.容量是哈希表中桶的数量,初始容量只是哈希表在创建时的容量.加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度.当哈希表 ...

  5. Java源码初学_ArrayList

    一.ArrayList的构造器和构造方法 在ArrayList中定义了两个空数组,分别对应当指定默认构造方法时候,指向的数组已经给定容量,但是容量等于0的时候,指向的数组.此外在构造函数中传入Coll ...

  6. 如何阅读Java源码 阅读java的真实体会

    刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我觉得最核心有三点:技术基础+强烈的求知欲+耐心.   说到技术基础,我打个比 ...

  7. Android反编译(一)之反编译JAVA源码

    Android反编译(一) 之反编译JAVA源码 [目录] 1.工具 2.反编译步骤 3.实例 4.装X技巧 1.工具 1).dex反编译JAR工具  dex2jar   http://code.go ...

  8. 如何阅读Java源码

    刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动.源码阅读,我觉得最核心有三点:技术基础+强烈的求知欲+耐心. 说到技术基础,我打个比方吧, ...

  9. Java 源码学习线路————_先JDK工具包集合_再core包,也就是String、StringBuffer等_Java IO类库

    http://www.iteye.com/topic/1113732 原则网址 Java源码初接触 如果你进行过一年左右的开发,喜欢用eclipse的debug功能.好了,你现在就有阅读源码的技术基础 ...

随机推荐

  1. C++智能指针管理类

    1.程序员明确的进行内存释放 对于c++程序员,最头脑的莫过于对动态分配的内存进行管理了.c++在堆上分配的内存,需要程序员负责对分配的内存进行释放.但有时内存的释放看起来并不件很轻松的事,如下程序 ...

  2. SQL语句,给自己的记录

    1.group by 和求和函数的使用 select className,SUM(num) as sumNum FROM test GROUP BY className 2.更新一个字段的所有值 up ...

  3. 第十二届浙江省大学生程序设计大赛-Demacia of the Ancients 分类: 比赛 2015-06-26 14:39 30人阅读 评论(0) 收藏

    Demacia of the Ancients Time Limit: 2 Seconds Memory Limit: 65536 KB There is a popular multiplayer ...

  4. Unity脚本在层级面板中的执行顺序测试1

    第二篇测试循环时和动态创建时的调用顺序:LINK 测试版本Unity4.6.因为新版本对Transform的排序做了改变,所以不排除旧版本的测试结果不一样.测试时,使用Awake中添加Debug.lo ...

  5. 更新yum源

    见地址: http://www.cnblogs.com/lightnear/archive/2012/10/03/2710952.html 163的不好用,执行失败,用alibaba的没有问题,如下: ...

  6. iis6兼容32位运行

    做web服务迁移,从32位win2003迁移到64位win2003,数据库是32位Oracle在另外一台服务器上. 迁移之后数据库各种连不上,oracle的客户端32位的装完装64位的,odp.net ...

  7. 转 Android学习笔记: 学习过程中碰到的一些问题及解决方法

    在学习Android开发的过程中遇到了不少的问题,所幸的是最终经过上网查询都得到了解决.现在将我在学习Android开发过程中遇到的一些问题及解决的方法整理如下. 1.R.java不能实时更新 问题描 ...

  8. struts2 + spring + mybatis 框架整合

    在Eclipse下基于Maven整合Struts2,Spring和Mybatis3框架. 新建Maven project,type选择webapp 工程目录如下 修改pom.xml文件如下: < ...

  9. Java中HashMap遍历的两种方式

    Java中HashMap遍历的两种方式 转]Java中HashMap遍历的两种方式原文地址: http://www.javaweb.cc/language/java/032291.shtml 第一种: ...

  10. uTenux——LED驱动讲解

    LED驱动讲解,对于一个嵌入式的工程师还是一个刚开是学习相关电子设计的朋友,对于LED的驱动问题应该不甚陌生.我所说的LED驱动并不是类似大功率LED照明的那个驱动,而是简单的控制器对LED的控制驱动 ...