【Java集合】-- LinkedList源码解析

目录

  • 继承体系
  • 数据结构
  • 源码解析
    • 1.属性
    • 2.构造方法
      • LinkedList()
      • LinkedList(Collection<? extends E> c)
    • 3.添加元素
      • add(E e)
      • addFirst(E e)
      • addLast(E e)
      • add(int index, E element)
      • offer(E e)
      • offerFirst(E e)
      • offerLast(E e)
      • 总结
    • 4.获取元素
      • get(int index)
      • getFirst()
      • getLast()
      • peek()
    • 5.删除元素
      • remove()
      • removeLast()
      • removeLast()
      • pollFirst()
      • pollLast()
  • 总结

LinkedList是一种以带头尾指针的双向链表实现的 List,与 ArrayList 相比,其插入元素快,不需要将元素向后移动,但是其获取元素却没有 ArrayList 方便。

继承体系

数据结构

在linkedList中维护了一个双向链表

源码解析

1.属性

//长度,默认为0
transient int size = 0;
//首节点
transient Node<E> first;
//尾节点
transient Node<E> last;

2.构造方法

LinkedList()

public LinkedList() {
}

LinkedList(Collection<? extends E> c)

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;
    //在链表的index处添加元素
    if (index == size) {
        succ = null;
        pred = last;
    } else {
        succ = node(index);
        pred = succ.prev;
    }

    //把c中元素添加到链表中
    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;
}

3.添加元素

add(E e)

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

addFirst(E e)

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

addLast(E e)

public void addLast(E e) {
    //同add方法通过尾插法,插入元素
    linkLast(e);
}

add(int index, E element)

public void add(int index, E element) {
    //边界值检测
    checkPositionIndex(index);
    if (index == size)
    //插入位置等于元素个数,直接插在链表尾部
        linkLast(element);
    else
    //获取对应index位置的元素
        linkBefore(element, node(index));
}
//把e元素生成的节点添加到succ前面
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++;
}

offer(E e)

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

将指定元素添加到链表尾部。

offerFirst(E e)

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

将指定元素添加到链表头

offerLast(E e)

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

链表尾部添加节点

总结

向链表中间添加元素效率较慢,为O(n)。其他方式添加元素快,时间复杂度为O(1)

4.获取元素

get(int index)

public E get(int index) {
    checkElementIndex(index);
    return node(index).item;
}
//获取指定索引位置的元素
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;
    }
}

getFirst()

public E getFirst() {
    final Node<E> f = first;
    if (f == null)
        throw new NoSuchElementException();
    return f.item;
}

getLast()

public E getLast() {
    final Node<E> l = last;
    if (l == null)
        throw new NoSuchElementException();
    return l.item;
}

peek()

public E peek() {
    final Node<E> f = first;
    return (f == null) ? null : f.item;
}

5.删除元素

remove()

public E remove() {
    return removeFirst();
}
public E removeFirst() {
    final Node<E> f = first;
    if (f == null)
        throw new NoSuchElementException();
    return unlinkFirst(f);
}
//判断是否为头节点,然后进行删除
private E unlinkFirst(Node<E> f) {
    // assert f == first && f != null;
    final E element = f.item;
    final Node<E> next = f.next;
    f.item = null;
    f.next = null; // help GC
    first = next;
    if (next == null)
        last = null;
    else
        next.prev = null;
    size--;
    modCount++;
    return element;
}

removeLast()

public E removeLast() {
    final Node<E> l = last;
    if (l == null)
        throw new NoSuchElementException();
    return unlinkLast(l);
}
//对尾节点进行删除
private E unlinkLast(Node<E> l) {
    // assert l == last && l != null;
    final E element = l.item;
    final Node<E> prev = l.prev;
    l.item = null;
    l.prev = null; // help GC
    last = prev;
    if (prev == null)
        first = null;
    else
        prev.next = null;
    size--;
    modCount++;
    return element;
}

removeLast()

public E removeLast() {
    final Node<E> l = last;
    if (l == null)
        throw new NoSuchElementException();
    return unlinkLast(l);
}

pollFirst()

public E pollFirst() {
    final Node<E> f = first;
    return (f == null) ? null : unlinkFirst(f);
}

pollLast()

public E pollLast() {
    final Node<E> l = last;
    return (l == null) ? null : unlinkLast(l);
}

总结

  • LinkedList是一个以双向链表实现的List;
  • LinkedList还是一个双端队列,具有队列、双端队列、栈的特性;
  • LinkedList在队列首尾添加、删除元素非常高效,时间复杂度为O(1);
  • LinkedList在中间添加、删除元素比较低效,时间复杂度为O(n);
  • LinkedList不支持随机访问,所以访问非队列首尾的元素比较低效;
  • LinkedList在功能上等于ArrayList + ArrayDeque;

ArrayList代表了List的典型实现,LInkedList代表了Deque的典型实现,同时LinkedList也实现了List,通过这两个类一首一尾正好可以把整个集合贯穿起来。

原文地址:https://www.cnblogs.com/wf614/p/12399049.html

时间: 2024-10-24 09:07:00

【Java集合】-- LinkedList源码解析的相关文章

Java集合---LinkedList源码解析

一.源码解析1. LinkedList类定义2.LinkedList数据结构原理3.私有属性4.构造方法5.元素添加add()及原理6.删除数据remove()7.数据获取get()8.数据复制clone()与toArray()9.遍历数据:Iterator()二.ListItr 一.源码解析 1. LinkedList类定义. public class LinkedList<E> extends AbstractSequentialList<E> implements List&

java集合类型源码解析之PriorityQueue

本来第二篇想解析一下LinkedList,不过扫了一下源码后,觉得LinkedList的实现比较简单,没有什么意思,于是移步PriorityQueue. PriorityQueue通过数组实现了一个堆数据结构(相当于一棵完全二叉树),元素的优先级可以通过一个Comparator来计算,如果不指定Comparator,那么元素类型应该实现Comparable接口.最终compare得出的最小元素,放在堆的根部. 成员变量 public class PriorityQueue<E> extends

Java集合-09LinkedHashMap源码解析及使用实例

LinkedHashMap 简介 hash表和链表实现了map接口,迭代顺序是可以预测的.LinkedHashMap和HashMap的不同是它所有的entry 维持了一个双向链表结构.该链表定义了通常迭代顺序是键插入的顺序. LinkedHashMap 定义 public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> 继承HashMap类,表明对于HashMap的操作LinkedHas

【java集合框架源码剖析系列】java源码剖析之TreeMap

注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本.本博客将从源码角度带领大家学习关于ArrayList的知识. 一TreeMap的定义: public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, java.io.Serializable 可以看到TreeMap是继承自AbstractMap同时实现了NavigableMap,

Java集合框架源码阅读之AbstractCollection

AbstractCollection是集合实现类的根抽象实现类,它实现了Collection接口,集合中的三个分支Set.List.Queue都是继承此类之后再进行各自实现的扩展,分别是AbstractSet.AbstractList.AbstractQueue.这三个分支有一些共同之处,需要用一些共同的方法,因此出现了AbstractCollection类,它包含了一些这三个分支都会用到的常用方法.而这三个分支也各有抽象类,因为这三个分支下面的一些具体实现也会有一些当前分支通用的方法,因此也给

Java集合框架之二:LinkedList源码解析

版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! LinkedList底层是通过双向循环链表来实现的,其结构如下图所示: 链表的组成元素我们称之为节点,节点由三部分组成:前一个节点的引用地址.数据.后一个节点的引用地址.LinkedList的Head节点不包含数据,每一个节点对应一个Entry对象.下面我们通过源码来分析LinkedList的实现原理. 1.Entry类源码: 1 private static class Entry<E> { 2 E element; 3 Entr

Java 集合Vector源码深入解析

概论 学完ArrayList和LinkedList之后,我们接着学习Vector.学习方式还是和之前一样,先对Vector有个整体认识,然后再学习它的源码:最后再通过实例来学会使用它. 第1部分 Vector介绍 Vector简介 Vector 是矢量队列,它是JDK1.0版本添加的类.继承于AbstractList,实现了List, RandomAccess, Cloneable这些接口.Vector 继承了AbstractList,实现了List:所以,它是一个队列,支持相关的添加.删除.修

【Java深入研究】2、LinkedList源码解析

一.源码解析 1. LinkedList类定义. public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable LinkedList 是一个继承于AbstractSequentialList的双向链表.它也可以被当作堆栈.队列或双端队列进行操作.LinkedList 实现 Li

Java 集合Hashtable源码深入解析

概要 前面,我们已经系统的对List进行了学习.接下来,我们先学习Map,然后再学习Set:因为Set的实现类都是基于Map来实现的(如,HashSet是通过HashMap实现的,TreeSet是通过TreeMap实现的). 首先,我们看看Map架构.如上图:(01) Map 是映射接口,Map中存储的内容是键值对(key-value).(02) AbstractMap 是继承于Map的抽象类,它实现了Map中的大部分API.其它Map的实现类可以通过继承AbstractMap来减少重复编码.(