JDK源代码学习系列05----LinkedList

1.LinkedList简单介绍

LinkedList是基于双向链表实现的,它也能够被当作堆栈、队列或双端队列进行操作。

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

LinkedList继承了AbstractSequentialList<E>,并实现了List<E>, Deque<E>, Cloneable, java.io.Serializable等接口。AbstractSequentialList 实现了get(int
index)、set(int index, E element)、add(int index, E element) 和 remove(int index)这些函数.



2.LinkedList的成员变量

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

LinkedList有两个成员变量,表头 header 和长度size.



3.LinkedList的构造函数

    public LinkedList() {//构造一个空链表
header.next = header.previous = header;
} public LinkedList(Collection<? extends E> c) {//将一个数据类型同样的集合加入到LinkedList的尾部
this();
addAll(c);
}



4.LinkedList的内部类。

a.Entry<E>是LinkedList的节点类,节点类包括:当前节点的值,前一节点。后一节点。该节点类是一个静态内部类:当内部类对象不须要訪问外围类对象时。应该声明为静态内部类。

 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;
}
}

b.ListItr 是 LinkedList 的迭代器类

 private class ListItr implements ListIterator<E> {
private Entry<E> lastReturned = header;//上一次返回的节点
private Entry<E> next;//下一节点
private int nextIndex;//下一节点的索引
private int expectedModCount = modCount;//!!!!!!期望的改变次数~ Java的 fail-fast 机制。 ListItr(int index) {
if (index < 0 || index > size)
throw new IndexOutOfBoundsException("Index: "+index+
", Size: "+size);
if (index < (size >> 1)) {//size>>1是右移一位。即size/2 ,若索引值小于 size/2则从前開始
next = header.next;
for (nextIndex=0; nextIndex<index; nextIndex++)
next = next.next;
} else {//否则从后開始
next = header;
for (nextIndex=size; nextIndex>index; nextIndex--)
next = next.previous;
}
} public boolean hasNext() {//是否存在下一个元素
return nextIndex != size;//通过下一节点索引值是否等于size来推断是否到了最末尾
} public E next() {
checkForComodification();
if (nextIndex == size)//!!
throw new NoSuchElementException(); lastReturned = next;
next = next.next;
nextIndex++;
return lastReturned.element;
} public boolean hasPrevious() {//是否存在上一个
return nextIndex != 0;//通过下一节点的索引值是否等于0来推断是否在最前面即头节点,由此来推断是否有前节点
} public E previous() {//取得上一元素
if (nextIndex == 0)
throw new NoSuchElementException(); lastReturned = next = next.previous; //????? ?
nextIndex--;
checkForComodification();
return lastReturned.element;
} public int nextIndex() {
return nextIndex;
} public int previousIndex() {//上一元素的索引
return nextIndex-1;
} public void remove() {//删除当前节点!!
checkForComodification();
Entry<E> lastNext = lastReturned.next;
try {
LinkedList.this.remove(lastReturned);
} catch (NoSuchElementException e) {
throw new IllegalStateException();
}
if (next==lastReturned)
next = lastNext;
else
nextIndex--;
lastReturned = header;
expectedModCount++;
} public void set(E e) {
if (lastReturned == header)
throw new IllegalStateException();
checkForComodification();
lastReturned.element = e;
} public void add(E e) {//讲e加入到当前节点前面
checkForComodification();
lastReturned = header;
addBefore(e, next);
nextIndex++;
expectedModCount++;
} final void checkForComodification() {//!!!!!推断 modCount是否等于 expectedModCount来实现fail-fast机制。
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}

c.

 private class DescendingIterator implements Iterator {
final ListItr itr = new ListItr(size());
public boolean hasNext() {
return itr.hasPrevious();
}
public E next() {
return itr.previous();
}
public void remove() {
itr.remove();
}
}

5.LinkedList的成员函数

因为LinkedList的成员函数非常多,就不单独每个做为一部分。把一些类似的函数放在一起。常常被调用的比較复杂的函数再单独介绍。

a.

   public E getFirst() {//取得第一个节点的值
if (size==0)
throw new NoSuchElementException();//时刻注意特殊情况的考虑
return header.next.element;
} public E getLast() {
if (size==0)
throw new NoSuchElementException();
return header.previous.element;//获得最后一个是 header.previous.element
} public E removeFirst() {//移除第一个节点
return remove(header.next);//remove函数以下单独介绍
} public E removeLast() {//移除最后一个节点
return remove(header.previous);
} public void addFirst(E e) {//在
addBefore(e, header.next);
} public void addLast(E e) {
addBefore(e, header);
} public boolean contains(Object o) {
return indexOf(o) != -1;
} public int size() {
return size;
} public boolean add(E e) {//在最末尾加入值为e的节点。加入在header前即最末尾
addBefore(e, header);
return true;
}

b. boolean remove(Object o)    /    E remove()     /     E remove(Entry<E> e)

    public boolean remove(Object o) {
if (o==null) {//即使是null也要查找到然后再移除
for (Entry<E> e = header.next; e != header; e = e.next) {
if (e.element==null) {
remove(e);//调用以下的方法
return true;
}
}
} else {
for (Entry<E> e = header.next; e != header; e = e.next) {
if (o.equals(e.element)) {
remove(e);
return true;
}
}
}
return false;
}
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;
}

c.boolean addAll(Collection<? extends E> c)  /    boolean addAll(int index, Collection<? extends E> c)

d.

 public void clear() {//清空LinkedList
Entry<E> e = header.next;
while (e != header) {
Entry<E> next = e.next;
e.next = e.previous = null;
e.element = null;
e = next;
}
header.next = header.previous = header;
size = 0;
modCount++;
} public E get(int index) {//获得某索引相应的节点值
return entry(index).element;
} public E set(int index, E element) {//设置某索引的节点值
Entry<E> e = entry(index);
E oldVal = e.element;
e.element = element;
return oldVal;
} public void add(int index, E element) {
addBefore(element, (index==size ? header : entry(index)));
} public E remove(int index) {//移除节点
return remove(entry(index));
}

e.Entry<E> entry(int index)

此方法得到某索引相应的节点对象

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)) {//若小于size/2,则从头遍历
for (int i = 0; i <= index; i++)
e = e.next;
} else {//否则从尾遍历
for (int i = size; i > index; i--)
e = e.previous;
}
return e;
}

f.

 public E peek() {//获取第一个元素的值
if (size==0)
return null;
return getFirst();
} public E element() {//获取第一个元素的值
return getFirst();
} public E poll() {//移除第一个元素
if (size==0)
return null;
return removeFirst();
} public E remove() {//移除第一个元素
return removeFirst();
} public boolean offer(E e) {
return add(e);
} public boolean offerFirst(E e) {
addFirst(e);
return true;
} public boolean offerLast(E e) {
addLast(e);
return true;
} public E peekFirst() {
if (size==0)
return null;
return getFirst();
} public E peekLast() {
if (size==0)
return null;
return getLast();
} public E pollFirst() {
if (size==0)
return null;
return removeFirst();
} public E pollLast() {
if (size==0)
return null;
return removeLast();
} public void push(E e) {
addFirst(e);
} public E pop() {
return removeFirst();
}

g.Entry<E> addBefore(E e, Entry<E> entry)

 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;
}

h.

   public Object[] toArray() {
Object[] result = new Object[size];
int i = 0;
for (Entry<E> e = header.next; e != header; e = e.next)
result[i++] = e.element;
return result;
} public <T> T[] toArray(T[] a) {
if (a.length < size)
a = (T[])java.lang.reflect.Array.newInstance(
a.getClass().getComponentType(), size);
int i = 0;
Object[] result = a;
for (Entry<E> e = header.next; e != header; e = e.next)
result[i++] = e.element; if (a.length > size)
a[size] = null; return a;
}

i.

private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
// Write out any hidden serialization magic
s.defaultWriteObject(); // Write out size
s.writeInt(size); // Write out all elements in the proper order.
for (Entry e = header.next; e != header; e = e.next)
s.writeObject(e.element);
} private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in any hidden serialization magic
s.defaultReadObject(); // Read in size
int size = s.readInt(); // Initialize header
header = new Entry<E>(null, null, null);
header.next = header.previous = header; // Read in all elements in the proper order.
for (int i=0; i<size; i++)
addBefore((E)s.readObject(), header);
}



5.方法归类

a.LinkedList能够作为FIFO(先进先出)的队列。作为FIFO的队列时。下表的方法等价:

队列方法       等效方法

add(e)        addLast(e)

offer(e)      offerLast(e)

remove()      removeFirst()

poll()        pollFirst()

element()     getFirst()

peek()        peekFirst()

b.LinkedList能够作为LIFO(后进先出)的栈,作为LIFO的栈时。下表的方法等价:

栈方法        等效方法

push(e)      addFirst(e)

pop()        removeFirst()

peek()       peekFirst()



6.总结

a.LinkedList是以双链表的形式实现的。

b.LinkedList即能够作为链表。还能够作为队列和栈。

c.LinkedList是 非 线程安全的。



JDK源代码学习系列05----LinkedList的更多相关文章

  1. JDK源代码学习系列07----Stack

                                                                   JDK源代码学习系列07----Stack 1.Stack源代码很easy ...

  2. JDK源代码学习系列04----ArrayList

                                                                             JDK源代码学习系列04----ArrayList 1 ...

  3. JDK源代码学习系列03----StringBuffer+StringBuilder

                         JDK源代码学习系列03----StringBuffer+StringBuilder 因为前面学习了StringBuffer和StringBuilder的父类 ...

  4. JDK源代码学习-ArrayList、LinkedList、HashMap

    ArrayList.LinkedList.HashMap是Java开发中非常常见的数据类型.它们的区别也非常明显的,在Java中也非常具有代表性.在Java中,常见的数据结构是:数组.链表,其他数据结 ...

  5. Java小白集合源码的学习系列:LinkedList

    目录 LinkedList 源码学习 LinkedList继承体系 LinkedList核心源码 Deque相关操作 总结 LinkedList 源码学习 前文传送门:Java小白集合源码的学习系列: ...

  6. JDK源代码学习-基础类

    一.概述 1.Java,是一套语言规范,例如规定了变量如何定义.控制语句如何写等,提供基本的语法规范.JDK是java自带的一套调用组件,是对基本java语法规范的进一步封装,jdk中都是使用java ...

  7. Java小白集合源码的学习系列:Vector

    目录 Vector源码学习 Vector继承体系 Vector核心源码 基本属性 构造器 扩容机制 Enumeration 概述 源码描述 具体操作 Vector总结 Vector源码学习 前文传送门 ...

  8. Java 集合系列05之 LinkedList详细介绍(源码解析)和使用示例

    概要  前面,我们已经学习了ArrayList,并了解了fail-fast机制.这一章我们接着学习List的实现类——LinkedList.和学习ArrayList一样,接下来呢,我们先对Linked ...

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

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

随机推荐

  1. Post+Get方式接口测试代码编写

    详细代码如下 package testproject; import java.io.BufferedReader; import java.io.IOException; import java.i ...

  2. 把一个project相关的jar放到project的lib文件夹中

    例如你有一个project名为xxx,/xxx 文件夹中有src.bin.等等,然后你手工创建一个lib文件夹,这样你就把解压出来的第三方lib(jar包,含javadoc)都放到lib文件夹中,这样 ...

  3. PHP学习笔记(5)GD库画验证码

    <?php header("content-type:image/png"); $width = 500; $height = 500; $img = imagecreate ...

  4. MVVM 实战之计算器

    MVVM 实战之计算器 android DataBinding MVVM calculator Model View 布局文件 Fragment ViewModel 结束语 前些日子,一直在学习基于 ...

  5. hadoop 调试mapperduce

    问题描述 运行hadoop的MapReduce示例,在running job卡住 在页面中显示一直处于 ACCEPTED Applications 状态 修改日志级别export HADOOP_ROO ...

  6. Unity3D中uGUI事件系统简述及使用方法总结

    Unity3D的uGUI系统的将UI可能触发的事件分为12个类型,即EventTriggerType枚举的12个值.如下图所示: 先以PointerClick为例.这个是用于某点点击事件.其他事件都可 ...

  7. shell常用的判断条件

    .判断文件夹是否存在 if [ -d /home/q/www ];then echo "true"; else echo "false" ;fi (系统内存在文 ...

  8. vSphere Web Client使用指南之安装配置

    vSphere Web Client使用指南之安装配置 vSphere Web Client是为忙碌的管理员提供的一款通用的.基于浏览器的VMware管理工具,能够监控并管理VMware基础设施.在摆 ...

  9. 转!sqlite3.OperationalError) no such table- users [SQL- 'SELECT users.id AS users_id, users.email AS u

    在注册新用户的时候报错: (sqlite3.OperationalError) no such table: users [SQL: 'SELECT users.id AS users_id, use ...

  10. CSS3自定义滚动条样式 -webkit-scrollbar (一)

    Webkit支持拥有overflow属性的区域,列表框,下拉菜单,textarea的滚动条自定义样式.当然,兼容所有浏览器的滚动条样式目前是不存在的. 滚动条的组成: ::-webkit-scroll ...