Java集合框架(十七):LinkedList 源码分析

文章目录

1、LinkedList 简述

1)Java LinkedList是List和Deque接口的实现。

2)在内部,LinkedList 是采用双向链表实现的,它包含一个很重要的内部类 Node。Node是双向链表节点所对应的数据结构,它包括的属性有:当前节点所包含的值,上一个节点,下一个节点。

3)它支持重复元素,并且可以添加任意数量的null元素。

4)它以插入顺序存储或维护它的元素。

5)它不是线程安全的,我们可以使用Collections.synchronizedList(new LinkedList(…));方法创建一个同步的链表。

6)在Java应用中,LinkedList 可以用作List,LIFO(后进先出)的栈或FIFO(先进先出)的队列。

7)它没有实现RandomAccess接口。 所以我们只能按顺序访问元素。 它不支持随机访问元素。

8)当我们尝试从 LinkedList 访问元素时,根据元素可用的位置搜索该元素从LinkedList的开头或结尾开始。

9)我们可以使用ListIterator来迭代LinkedList元素。

10)从LinkedList的实现方式中可以发现,它不存在LinkedList容量不足的问题。

11)LinkedList 的克隆函数(clone()),是将全部元素克隆到一个新的LinkedList对象中。

12)LinkedList 实现java.io.Serializable。当写入到输出流时,先写入“容量”,再依次写入“每一个节点保护的值”;当读出输入流时,先读取“容量”,再依次读取“每一个元素”。

13)由于LinkedList实现了Deque,而Deque接口定义了在双端队列两端访问元素的方法。提供插入、移除和检查元素的方法。每种方法都存在两种形式:一种形式在操作失败时抛出异常,另一种形式返回一个特殊值(null 或 false,具体取决于操作)

14)从Java 8开始,我们可以将LinkedList 转换为 Stream,反之亦然。

15)Java 9 添加了几个工厂方法来创建一个Immutable LinkedList。

2、LinkedList 类图

众所周知,Java LinkedList是List实现类之一。
java.util.LinkedList 继承了 AbstractSequentialList 并实现了List , Deque , Cloneable 以及Serializable 接口

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

在这里插入图片描述

2.1、LinkedList 内部结构

LinkedList内部结构是一个双向链表

在这里插入图片描述

每一个节点都是一个Node 对象,由三个元素组成

private static class Node<E> {
        // E类型的值item  
        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;
        }
}

3、LinkedList 成员变量

3.1、size 链表的节点数量

初始化链表的长度为0

 transient int size = 0;

3.2、first 指向第一个节点的指针

    /**
     * 指向第一个节点的指针
     * Invariant: (first == null && last == null) ||
     *            (first.prev == null && first.item != null)
     */
    transient Node<E> first;

3.3、last 指向最后一个节点的指针

    /**
     * 指向最后一个节点的指针。
     * Invariant: (first == null && last == null) ||
     *            (last.next == null && last.item != null)
     */
    transient Node<E> last;

4、LinkedList 构造函数

4.1、LinkedList()

构造一个空列表。

public LinkedList() {}

4.2、LinkedList(Collection<? extends E> c)

    /**
     * 按照集合的迭代器返回的顺序构造一个包含指定集合元素的列表。
     *
     * @param  c 要将其元素放入此列表的集合
     * @throws NullPointerException 如果指定集合为null
     */
    public LinkedList(Collection<? extends E> c) {
        this();
         //使用addAll方法,实际上就是遍历c并且采用头插法进行双向链表插入值。  
        addAll(c);
    }

5、LinkedList 方法

由于LinkedList实现了Deque,而Deque接口定义了在双端队列两端访问元素的方法。提供插入、移除和检查元素的方法。每种方法都存在两种形式:一种形式在操作失败时抛出异常,另一种形式返回一个特殊值(null 或 false,具体取决于操作)

操作 头部元素 尾部元素
返回值 抛出异常 特殊值 抛出异常 特殊值
插入 addFirst(e) offerFirst(e) addLast(e)  offerLast(e)
移除 removeFirst() pollFirst()  removeLast()  pollLast()
检索 getFirst()  peekFirst() getLast()  peekLast()

LinkedList 可以作为 FIFO(先进先出)的队列,作为FIFO的队列时,下面的方法是等价的

队列方法 等价方法
add(e) addLast(e)
offer(e) offerLast(e)
remove() removeFirst()
poll() pollFirst()
element() getFirst()
peek() peekFirst()

LinkedList 可以作为 LIFO(后进先出)的栈,作为LIFO的栈时,下面的方法是等价的

栈方法 等价方法
push(e) addFirst(e)
pop() removeFirst()
peek() peekFirst()

5.1、LinkedList 获取元素

5.1.1、public E get(int index)

获取指定索引处节点的元素,首先对指定索引进行越界检查,如果未越界返回相应位置node节点的元素;否则,抛出 IndexOutOfBoundsException 异常

    /**
     * 返回此列表中指定位置的元素。
     *
     * @param index 要返回的元素的索引值
     * @return 列表中指定位置的元素
     * @throws IndexOutOfBoundsException 
     */
    public E get(int index) {
        //索引越界检查
        checkElementIndex(index);
        return node(index).item;
    }
    
    private void checkElementIndex(int index) {
        if (!isElementIndex(index))
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
    /**
     * 判断参数是否是现有元素的索引。
     */
    private boolean isElementIndex(int index) {
        return index >= 0 && index < size;
    }
    
     /**
     * 构造一个IndexOutOfBoundsException详细消息。
     * 
     */
    private String outOfBoundsMsg(int index) {
        return "Index: "+index+", Size: "+size;
    }
    
    /**
     * 返回指定元素索引处的(非null)节点。
     */
    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 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值