jdk 1.7 LinkedList 源码分析

1 linkedList 的定义

public class LinkedList<E>

extends AbstractSequentialList<E>

implements List<E>, Deque<E>, Cloneable, java.io.Serializable

从这段代码中我们可以清晰地看出LinkedList继承AbstractSequentialList,实现List、Deque、Cloneable、Serializable。其中AbstractSequentialList提供了 List 接口的骨干实现,从而最大限度地减少了实现受“连续访问”数据存储(如链接列表)支持的此接口所需的工作,从而以减少实现List接口的复杂度。Deque一个线性 collection,支持在两端插入和移除元素,定义了双端队列的操作。

从中可以看出LinkedList既实现了List接口也实现了双向队列的接口

2、属性

transient int size = 0;

transient Node<E> first;

transient Node<E> last;

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;

}

}

size 记录链表中的节点个数,LinkedList是个双向链表所以有前后两个节点,在LinkedList里有个内部类即节点类node

3、构造方法

public LinkedList() {

}

默认的构造方法内不做任何操作

public LinkedList(Collection<? extends E> c) {

this();

addAll(c);

}

public boolean addAll(Collection<? extends E> c) {

return addAll(size, c);

}

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;

}

for (Object o : a) {

@SuppressWarnings("unchecked") E e = (E) o;

Node<E> newNode = new Node<>(pred, e, null);

if (pred == null)

first = newNode;

else

pred.next = newNode;

pred = newNode;

}

if (succ == null) {

last = pred;

} else {

pred.next = succ;

succ.prev = pred;

}

size += numNew;

modCount++;

return true;

}

参数是集合的构造函数,他调用了addAll(c) 方法,addAll(c)中有调用了addAll(size, c)方法,size代表的是插入的下标位置,然后为每个对象一个一个地创造node类,然后进行链表插入操作,addAll()方法中调用了node(index)函数,该函数是查找到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;

}

}

该函数的思想是判断index在前半段还是在后半段,若在前半段用first遍历 若在后半段用last遍历

4、增加方法

public boolean add(E e) {

linkLast(e);

return true;

}

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

}

直接调用add()方法参数是一个对象,实际上是在链表最后加上新的节点,让last指向新的节点

public void add(int index, E element) {

checkPositionIndex(index);

if (index == size)

linkLast(element);

else

linkBefore(element, node(index));

}

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

}

在指定下标位置插入新的对象,先判断index是否有效,有效位置为0-size , 如果为size 直接调用add()函数加到链表尾,否则调用 linkBefore()函数

其他的还有

public boolean addAll(Collection<? extends E> c) {

return addAll(size, c);

}

////////////////////////////////////////往链表前加入新的对象

public void addFirst(E e) {

linkFirst(e);

}

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

}

//////////////////////////////////////////////////////////////////////////////////////////

在链表后加入新的节点

public void addLast(E e) {

linkLast(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++;

}

5、删除方法

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;

}

E unlink(Node<E> x) {

// assert x != null;

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;

}

该方法是删除链表中的某个对象,实际上是个遍历链表比较的一个过程,分两种情况,删除的对象是否为null,删除的是最小index符合条件的对象并不是删除链表中满足条件的所有对象

public E remove(int index) {

checkElementIndex(index);

return unlink(node(index));

}

删除在index位置上的对象

其他方法还有:

removeFirst() 删除头结点

removeLast() 删除末尾节点

removeFirstOccurrence(Object o) 删除从头到尾遍历是o的第一个对象 实际上调用的是remove(Object o) 两者是一个概念

removeLastOccurrence(Object o) 删除从尾到头遍历是o的第一个对象

6、查找方法

public E get(int index) {

checkElementIndex(index);

return node(index).item;

}

返回下标位置为index的对象内容

public E getFirst() {

final Node<E> f = first;

if (f == null)

throw new NoSuchElementException();

return f.item;

}

返回头结点内容

public E getLast() {

final Node<E> l = last;

if (l == null)

throw new NoSuchElementException();

return l.item;

}

返回尾节点的内容

 

7序列化与反序列化

从定义中LinkedList实现了serializable 所以可以进行序列化 ,在源码中有对序列化和反序列化的函数进行重写

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 (Node<E> x = first; x != null; x = x.next)

s.writeObject(x.item);

}

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();

// Read in all elements in the proper order.

for (int i = 0; i < size; i++)

linkLast((E)s.readObject());

}

}

时间: 2024-08-02 02:43:32

jdk 1.7 LinkedList 源码分析的相关文章

Java集合系列之LinkedList源码分析

一.LinkedList简介 LinkedList是一种可以在任何位置进行高效地插入和移除操作的有序序列,它是基于双向链表实现的. ps:这里有一个问题,就是关于实现LinkedList的数据结构是否为循环的双向链表,上网搜了有很多文章都说是循环的,并且有的文章中但是我看了源代码觉得应该不是循环的? 例如在删除列表尾部节点的代码: private E unlinkLast(Node<E> l) { final E element = l.item; final Node<E> pr

Java中arraylist和linkedlist源码分析与性能比较

Java中arraylist和linkedlist源码分析与性能比较 1,简介 在java开发中比较常用的数据结构是arraylist和linkedlist,本文主要从源码角度分析arraylist和linkedlist的性能. 2,arraylist源码分析 Arraylist底层的数据结构是一个对象数组,有一个size的成员变量标记数组中元素的个数,如下图: * The array buffer into which the elements of the ArrayList are sto

LinkedList源码分析--jdk1.8

JDK1.8 ArrayList源码分析--jdk1.8LinkedList源码分析--jdk1.8 LinkedList概述 ??1.LinkedList是用双向链表实现的集合,基于内部类Node<E>实现的集合.??2.LinkedList支持双向链表访问.克隆.序列化,元素有序且可以重复.??3.LinkedList没有初始化大小,也没有扩容机制,通过头结点.尾节点迭代查找. LinkedList数据结构 ??数据结构是集合的精华所在,数据结构往往也限制了集合的作用和侧重点,了解各种数据

LinkedList 源码分析(JDK 1.8)

1.概述 LinkedList 是 Java 集合框架中一个重要的实现,其底层采用的双向链表结构.和 ArrayList 一样,LinkedList 也支持空值和重复值.由于 LinkedList 基于链表实现,存储元素过程中,无需像 ArrayList 那样进行扩容.但有得必有失,LinkedList 存储元素的节点需要额外的空间存储前驱和后继的引用.另一方面,LinkedList 在链表头部和尾部插入效率比较高,但在指定位置进行插入时,效率一般.原因是,在指定位置插入需要定位到该位置处的节点

Java - LinkedList源码分析

java提高篇(二二)---LinkedList 一.概述 LinkedList与ArrayList一样实现List接口,只是ArrayList是List接口的大小可变数组的实现,LinkedList是List接口链表的实现.基于链表实现的方式使得LinkedList在插入和删除时更优于ArrayList,而随机访问则比ArrayList逊色些. LinkedList实现所有可选的列表操作,并允许所有的元素包括null. 除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾

LinkedList 源码分析

一.概述 本文基于 JDK8 LinkedList 底层通过双向集合的数据结构实现 内存无需连续的空间保证 元素查找只能是顺序的遍历查找 针对增删操作具有更好的性能 LinkedList 可以作为 List 使用,也可以作为队列和栈使用.支持从集合的头部,中间,尾部进行添加.删除等操作. LinkedList 的继承与实现的关系图如下所示. 以下说明摘自 JDK 文档. Iterable 接口:提供迭代器访问能力,实现此接口允许对象通过 for-each 循环语句进行遍历. Collection

死磕 java集合之LinkedList源码分析

问题 (1)LinkedList只是一个List吗? (2)LinkedList还有其它什么特性吗? (3)LinkedList为啥经常拿出来跟ArrayList比较? (4)我为什么把LinkedList放在最后一章来讲? 简介 LinkedList是一个以双向链表实现的List,它除了作为List使用,还可以作为队列或者栈来使用,它是怎么实现的呢?让我们一起来学习吧. 继承体系 通过继承体系,我们可以看到LinkedList不仅实现了List接口,还实现了Queue和Deque接口,所以它既

LinkedList源码分析

LinkedList的声明 public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable 基本和ArrayList一样,除了实现了Deque<E>接口以及没有实现RandomAccess接口. Deque是double ended queue(双端队列)的缩写,表示

Java进阶之----LinkedList源码分析

今天在看LinkedList的源代码的时候,遇到了一个坑.我研究源码时,发现LinkedList是一个直线型的链表结构,但是我在baidu搜索资料的时候,关于这部分的源码解析,全部都说LinkedList是一个环形链表结构..我纠结了好长时间,还以为我理解错了,最后还是在Google搜到了结果:因为我看的源码是1.7的而baidu出来的几乎全部都是1.6的.而且也没有对应的说明.在1.7之后,oracle将LinkedList做了一些优化,将1.6中的环形结构优化为了直线型了链表结构.这里要提示