JDK9.0 LinkedList源码阅读记录

概述

LinkedList继承体系
java.lang.Object
     java.util.AbstractCollection<E>
        java.util.AbstractList<E>
          java.util.AbstractSequentialList<E>
              java.util.LinkedList<E>
LinkedList定义
public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable

说明:
1.LinkedList是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。
3.LinkedList 实现 List 接口,能进行队列操作。
4.LinkedList 实现Deque接口,即能将LinkedList当作双端队列使用。
5.LinkedList 实现了Cloneable接口,即覆盖了函数clone(),能克隆。
6.LinkedList 实现java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。
7.LinkedList 是非同步的。
8.ArrayList底层是由数组支持,而LinkedList是由双向链表实现的,其中的每个对象包含数据的同时还包含指向链表中前一个与后一个元素的引用。

LinkedList方法

public LinkedList();//无参构造器
public LinkedList(Collection<? extends E> c) ;//构造器,以集合c创建LinkedList对象
void linkLast(E e);//给linkFirst的添加last节点添加元素
void linkBefore(E e, Node<E> succ);//在节点succ之前插入元素 
private E unlinkFirst(Node<E> f);//移除节点,用于移除首节点
private E unlinkLast(Node<E> l);//移除节点,用于移除尾节点
E unlink(Node<E> x);//移除x节点
public E getFirst();//获取首节点
public E getLast() ;//获取尾节点
public E removeFirst();//移除首节点
public E removeLast();//移除尾节点 
public void addFirst(E e) ;//添加元素作为首节点
public void addLirst(E e) ;//添加元素作为尾节点
public boolean contains(Object o);//判断是否包含对象o
public int size();//获取当前的包含的元素数量
public boolean add(E e);//添加元素
public boolean remove(Object o);//移除对象
public boolean addAll(Collection<? extends E> c) ;//添加集合c的所有元素
public boolean addAll(int index, Collection<? extends E> c);//在index处 添加集合c的所有元素 
public E get(int index) ;//获取索引为index的元素

......等
源代码分析
单向链表和双向链表

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
双向链表添加节点
单向链表(单链表)是链表的一种,它由节点组成,每个节点都包含下一个节点的引用。
双向链表(双链表)是链表的一种。和单链表一样,双链表也是由节点组成,它的每个数据结点中都有两个引用指向前后节点,分别指向直接前驱和直接后继。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。

LinkedList节点

一个节点包含了元素值,前驱引用和后置引用,可以很方面的找到前后节点.

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;
        }
    }
三个属性
transient int size = 0;  //元素的数量
transient Node<E> first; //指向第一个节点
transient Node<E> last;//指向末尾节点
添加节点

可以看出,添加节点时,只是改变节点的next和prev指向即可,因此效率很高

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++;
}
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++;
}
删除节点

可以看出,删除节点时,只是改变节点的next和prev指向即可,因此效率很高

 E unlink(Node<E> x) {
    // assert x != null;
    final E element = x.item;
    final Node<E> next = x.next;
    final Node<E> prev = x.prev;

    if (prev == null) {
        first = next;
    } else {
        prev.next = next;
        x.prev = null;
    }

    if (next == null) {
        last = prev;
    } else {
        next.prev = prev;
        x.next = null;
    }

    x.item = null;
    size--;
    modCount++;
    return element;
}
查找/删除/设置指定位置的节点元素

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;
      }
  }
迭代器

有两个迭代器Iterator和ListIterator,使用其来对元素进行遍历
两个的实现类都是实现了Iterator接口.
从以下可以看出ListIterator提供的功能更多.
Iterator

public boolean hasNext()
public E next() 
public void remove()

ListIterator

public boolean hasNext();//是否还存在后节点
public E next();//获取当前的元素值
public boolean hasPrevious();//是否存在前节点
public E previous();//获取当前的元素值
public int nextIndex();//获取当前迭代的索引
public int previousIndex();//获取当前迭代的索引
public void remove();//移除元素
public void set(E e) ;//设置当前迭代到元素
public void add(E e);//添加元素至末节点

总结

  1. 与ArrayList相比,ArrayList的数据结构是动态数组,LinkedList的数据结构是双向链表.
  2. LinkedList也可以通过索引进行定位,但是其是通过遍历来进行定位,效率较低,而且只使用了一次二分法.
  3. LinkedList没有进行同步处理,因此会存在线程不安全性,使用时需要注意.
  4. 可以使用迭代器进行访问. 
  5. 实现clone方法,可以被拷贝.
  6. 可以被序列化 .
  7. 相比于 ArrayList,保存同等的数据量的情况下,LinkedList所占用的空间更大,因为每个节点都要保存前后节点的引用.
  8. LinkedList的效率请看这里ArrayList和LinkedList性能比较

相关文章

JDK9.0 ArrayList源码阅读记录
JDK9.0 LinkedList源码阅读记录
ArrayList和LinkedList性能比较
JDK9.0 Vector源码阅读记录
JDK9.0 Hashtable源码阅读记录
Java9.0 HashMap源码阅读记录
JDK9.0 HashSet源码阅读记录

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值