Java LinkedList 源码分析

源码均以JDK8作为参考

LinkedList在JDK1.2中引入,继承自AbstractSequentialList<E>抽象类和实现了List<E>接口,JDK1.5进行Collection框架重构时,由于其链表的特性与Queue及其相似,

LinkedList实现了Queue<E>接口,

在JDK1.6中由于新引入了Deque<E>双端队列(Deque<E>继承自Queue<E>),LinkedList放弃Queue<E>接口,通过实现Deque<E>接口,间接的实现了Queue<E>接

口。由于LinkedList在JDK版本上升过程中的多次升级,使得LinkedList本身的方法存在部分的重叠部分,这些部分都是针对不同的数据结构的实现,但是在LinkedList中,他

们的作用是相同的,而且存在着相互引用的关系。

1.LinkedList是一个Doubly-linked list, 即双向链表,实现了自前自后的索引方式。

描述LinkedList是一个双向链表,是因为LinkedList通过特有的私有内部类实现了一个链,链上的每个节点知晓前后节点引用,因此可以向前向后索引。

3.LinkedList提供两个构造方法初始化

public LinkedList()

: 构建一个空的LinkedList对象

public LinkedList(Collection<? extends E> c)

: 构建一个空的LinkedList对象,将集合c加入到链表中

3.LinkedList类内部只有三个用于记录结构信息的变量

size:当前LinkedList内部元素个数

first:链表头部Node<E>元素

last:链表尾部Node<E>元素

2.LinkedList链节点实现Node<E>:

Node<E>源码如下:

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

    item:当前元素的值

    next:下一个Node<E>节点的索引

    prev:上一个Node<E>节点的索引

LinkedList持有First和Last节点的索引,而每个节点都有item、next、prev的值,因此LinkedList可以通过持有的First和Last节点自前自后遍历整个链表。

4.E get(int):方法分析

由于LinkedList是一个双向链表,因此在索引时,其速度较于ArrayList和Vector(ArrayList和Vector基于数组实现)要慢很多,因此在get(int)方法调用时,LinkedList内部实现

并非按照单一的方式进行索引的。

源码如下:

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 < (size >> 1)时(注:size >> 1是移位操作),从链表头部开始查找,当index >= (size >> 1)时,从链表尾部开始查找。LinkedList这样的操作是在避免链表

本身造成的索引低下的问题。

5.遍历:

ArryList<E>和Vector<E>实现了RandomAccess接口,RandomAccess接口是一个标记接口,实现此接口表明该类支持快速索引,即for遍历,且for遍历的速度优于Iterator

迭代的速度。

LinkedList<E>没有实现RandomAccess,因此LinkedList<E>的Iterator迭代速度要优于for遍历的速度。

示例代码如下:

List<String> list = new LinkedList<String>();
list.add("123");
list.add("456");
list.add("789");
    
Iterator it = list.iterator();
while(it.hasNext()){
    System.out.println(it.next());
}

    当然也可以使用for遍历:

 

for(int i = 0;i<list.size(); i++){
    System.out.println(list.get(i));
}

 

 6.应用场景

  由于LinkedList具有链表的特性,而链表结构的优点是便于向集合中插入和删除对象。那么经常向集合中插入或删除对象,应用LinkedList效率较高。但是LinkedList的随

机访问效率比较低下。这种分析都是在一定的数据量基础之上的,比如,虽然LinkedList拥有列表的高速插入和删除特性,但是数据达到一定数量级,依然没有基于数组的

ArrayList效率高。所以因时制宜,根据不同的应用场景选用不同的数据结构,才是正解。

 

LinkedList所有public方法:由于LinkedList在JDK版本更迭过程中的多次修改,其公开方法来自于三个接口的实现,尽管实现的接口不同,但是对外开放的功能是相同

 

的,在JDK1.5和JDK1.6的实现过程中,很多方法都是直接基于JDK1.2版本已有的功能实现的。

JDK1.2:AbstractSequentialList<E>和List<E>的方法实现

E getFirst(): 获取链表头元素

E getLast(): 获取链表尾元素

E removeFirst(): 移除链表头元素

E removeLast(): 移除链表尾元素

void addFirst(E e):在链表头部加入元素

void addLast(E e): 在链表尾部加入元素

boolean contains(Object o):是否包含指定元素

int size():获取链表内元素数

boolean add(E e): 在链表尾部加入元素

boolean remove(Object o): 在链表中移除指定元素

boolean addAll(Collection<? extends E> c): 将集合c中的元素加入到链表尾部

boolean addAll(int index, Collection<? extends E> c): 在指定index位置加入集合c的元素

void clear(): 清空链表

E get(int index): 获取index位置处的元素

E set(int index, E element): 替换index位置处的元素element

void add(int index, E element): 在index位置处加入元素element

E remove(int index):移除index位置处的元素

int indexOf(Object o): 获取元素o的位置index

int lastIndexOf(Object o): 获取元素o的位置index,从链尾向前

ListIterator<E> listIterator(int index):从指定位置获取迭代器

public Object clone(): 拷贝,浅拷贝

public Object[] toArray(): 链表转换为数组

JDK1.5:Queue<E>的方法实现

E peek(): 遍历检索,获取链表头元素,但不移除头元素,若链表为空,返回null

E element(): 遍历索引,获取链表头元素,若链表为空,抛出异常

E poll():遍历索引,获取链表头元素,并移除头元素,若链表为空,返回null

E remove():移除链表头元素,若链表为空,返回null

boolean offer(E e):在链表尾部加入元素e

JDK1.6:Deque<E>的方法实现

boolean offerFirst(E e):在链表头部加入元素e

public boolean offerLast(E e):在链表尾部加入元素e

E peekFirst(): 遍历索引,获取链表头元素,但不移除头元素,若链表为空,返回nulll

E peekLast(): 遍历索引,获取链表尾元素,但不移除尾元素,若链表为空,返回nulll

E pollFirst(): 获取链表头元素,并移除头元素,若链表为空,返回null

E pollLast():  获取链表尾元素,并移除尾元素,若链表为空,返回null

void push(E e): 插入链表头元素

E pop():获取链表头元素,并移除

boolean removeFirstOccurrence(Object o):移除元素o,自前向后索引

boolean removeLastOccurrence(Object o):移除元素o,自后向前索引

public Iterator<E> descendingIterator(): 获取典型迭代器
 

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值