LinkedList源码超详细解析

LinkedList源码分析

众所周知,LinkedList实现了List接口,LinkedList适用于集合元素先入先出和先入后出的场景,在队列的源码中被频繁使用,我们在使用一般的队列时,就直接可以拿LinkedList来实现,如下:

        LinkedList<Integer> queue = new LinkedList<>();
        queue.addLast(3);  //相当于入队操作
        queue.addLast(4);
        queue.addLast(5);
        System.out.println(queue.removeFirst());  //相当于出队操作(poll)
        System.out.println(queue.getFirst());   //相当于peek操作

可见LinkedList的操作十分的灵活!!

1. 整体架构

LinkedList的底层结构是一个双向链表,如下图:
在这里插入图片描述
看到上图的结构,注意到:

  • 当链表中没有数据的时候,first和last是同一个节点,前后指向都为零;
  • 双向链表大小只受内存大小的限制;

1. 类定义

先来看看这个类的定义:

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

注意到了没,他还实现了Deque这个接口,所以LinkedList中还实现了poll()、peek()、push()、pop()等等,这些方法都是实现了Deque这个接口里的抽象方法,而这些方法的实现,就是基于LikedList里面本来的add、remove系列操作,比如看push()和pop()和peek()这三个方法:

    public void push(E e) {
   
        addFirst(e);   //头插法新增节点
    }
    public E pop() {
     //删除头节点
        return removeFirst();
    }
    public E peek() {
      //返回头节点
        final Node<E> f = first;
        return (f == null) ? null : f.item;
    }

2. 底层结构

在LinedList里面有一个为Node的静态内部类:(这正是我们的底层结构)

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

3. 常用方法源码解析

1. 构造方法

有两个构造方法,一个是无参构造,一个是传入一个Collection集合,注意该集合的泛型得是当前定义的泛型的子类!

    public LinkedList() {
   
    }
	//该构造函数将传入的集合(符合要求的)转化为LinkedList
    public LinkedList(Collection<? extends E> c) {
   
        this();
        addAll(c);
    }

注意第二个构造函数:

  • 当传入的集合泛型不符合条件时,则会编译出错;
2. 新增操作

即为双向链表,所以新增节点的操作可以为头插,也可以是尾插;

在LikedList里面,定义了两个节点:

    transient Node<E> first;
    transient Node<E> last;

这两个初始值都为null;

1. add()方法(尾插)

add方法默认是从尾部开始增加节点的:

    public boolean add(E e) {
   
        linkLast(e);
        return true;
    }
    void linkLast(E e) {
   
        //先获取尾节点
        final Node<E> l = last;
        //这里通过构造方法就将newNode的prev设置为last,next设置为空
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        //判断是不是空链表(插入前)
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        //记录更改
        modCount++;
    }
2. addFirst()方法 (头插)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值