Java之LinkedList源码分析(第四篇:添加元素-Deque接口)

(注意:本文源码基于JDK1.8)   

Deque接口扩展了Queue接口,LinkedList实现了Deque接口,Deque接口表示双端队列的能力,双端队列在线性表的两端都可以插入元素与删除元素。本文分析与Deque接口相关的添加元素的方法:addFirst、addLast、offerFirst、offerLast、add、offer,共计6个方法

(图示为持有三个元素的LinkedList对象)

 

addFirst()方法分析

    public void addFirst(E e) {
        linkFirst(e);
    }

用于向双向链表的头部添加一个元素的方法,传入的参数表示一个参数类型为E的元素对象

在方法体中,直接将传入的元素对象e传入到linkFirst()方法中进行插入元素的工作(在第三篇文章中,曾分析过此方法)

 

linkFirst()方法分析

    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的元素对象

1、获取当前LinkedList对象持有的第一个元素

首先取出LinkedList对象持有的指向第一个结点对象的实例变量first,并由局部变量f保存,局部变量f为final修饰,不允许再次修改

2、创建的新的Node对象,用于持有元素对象

创建一个新的Node对象,Node对象需持有添加的元素对象e、以及旧的头结点对象f,新的Node对象由局部变量newNode负责保存(提示:Node对象持有的next会连接(指向)到原来的第一个结点对象f)

3、变更LinkedList对象持有的first指向新添加的元素

将LinkedList对象持有的first指向新创建的结点对象newNode,此时first指向了新插入的第一个结点对象

4、对首次添加元素作处理

如果LinkedList是第一次添加元素,则LinkedList对象持有的last,也会指向新添加的结点对象newNode

5、针对LinekdList非首次添加元素作处理

如果不是第一次添加元素,则旧的头结点对象持有的prev需要指向新创建的结点对象newNode(因为旧的头结点成为了第二个结点对象)

6、更新元素总数

LinkedList对象持有的元素总数size需要加1(size++)

7、fail-fast机制更新

代表LinkedList的元素发生改变的modCount也加1(modCount++)

此时的方法已经添加元素成功,引用是这么重要呀,哈哈!

 

offerFirst()方法分析

    public boolean offerFirst(E e) {
        addFirst(e);
        return true;
    }

用于向双向链表的头部添加一个元素,返回值表示添加元素成功,传入参数类型E的元素对象

1、调用addFirst()方法添加元素

offerFirst()方法中,没有再去实现添加元素的方法,而是直接将传入的元素对象e再传入到addFirst()方法中完成向双向链表头部添加元素

2、向调用者返回添加元素的结果

返回值为true,代表成功添加一个元素

 

add()方法分析

    public boolean add(E e) {
        linkLast(e);
        return true;
    }

看起来面熟吧?之前我也分析了一个add()方法,没错,它们是同一个方法,List接口与Deque接口都规范了一个称作add的方法,此处LinkedList在实现add()方法时,只要实现一个具体的方法即可,具体源码分析请看【第三篇:添加元素-List接口】

 

addLast方法()分析

    public void addLast(E e) {
        linkLast(e);
    }

用于将元素添加到双向链表尾部的方法,传入的参数为类型参数E的对象

与addFirst()方法不同,addLast()方法添加的元素是在线性表的尾部,内部调用linkLast()方法完成元素的添加

 

linkLast()方法分析

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

用于向双向链表的尾部添加一个元素,在第三篇添加元素的文章中已经做了分析,这里作为复习!

1、本地获取最后一个节点对象

首先将LinkedList对象持有的最后一个结点对象的实例变量last,先保存到局部变量l中

2、创建新的Node对象

新创建一个Node对象,Node对象持有了局部变量l、元素对象e、以及一个null值,然后把该Node对象先由局部变量newNode负责保管,局部变量l与newNode均为final修饰,这样可以保证他们不能再被赋值。

3、第一次添加元素、非第一次添加元素的分开处理

新插入的元素对象在双向链表的尾部,所以LinedList对象持有的实例变量last则指向最新创建的Node对象newNode。根据当前LinkedList的情况,为持有的结点对象赋值,如果last为null,说明当前LinkedList还没有持有元素,此时新创建的newNode会赋值给LinkedList对象持有的first,即新创建的结点对象也是第一个结点,另外一种情况则是last不为null,说明当前LinkedList已经持有元素,此时会将旧的尾结点对象l持有的实例变量next指向新创建的结点对象newNode

4、最后则是将LinkedList的实际持有元素数量size加上1(size++),还有modCount结果也加1(modCount++),此时元素的添加过程已经完成

 

offerLast()方法分析

    public boolean offerLast(E e) {
        addLast(e);
        return true;
    }

内部实际调用addLast()方法完成插入元素的操作,比addLast()方法只多了一条语句,返回值true表示插入元素成功

 

offer()方法分析

    public boolean offer(E e) {
        return add(e);
    }

用于向双向链表的尾部添加元素,内部实际调用的是add()方法具体源码分析请看【第三篇:添加元素-List接口】,add()方法的返回值将作为offer()方法的返回值

 

总结

1、offerFirst()方法内部调用的是addFirst()方法,offerFirst()方法只比addFirst()方法多了一个boolean值,其他都一样

2、offerLast()方法内部调用的是addLast()方法,自己没有做添加元素的具体实现

3、offer()方法内部调用的是add()方法完成实际添加元素的工作

4、添加元素的方法实际调用的是linkFirst()方法或者linkLast()方法完成添加元素工作

addFirst()与offerFirst()方法,元素添加到双向链表的头部

add()方法与offer()方法,元素添加到双向链表的尾部

addLast()与offerLast()方法,元素添加到双向链表的尾部

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值