Java集合框架源码解读——Collection - LinkedList源码解析
Posted 傲骄鹿先生
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java集合框架源码解读——Collection - LinkedList源码解析相关的知识,希望对你有一定的参考价值。
我是傲骄鹿先生,沉淀、学习、分享、成长。
如果你觉得文章内容还可以的话,希望不吝您的「一键三连」,文章里面有不足的地方希望各位在评论区补充疑惑、见解以及面试中遇到的奇葩问法
目录
removeFirest(), removeLast(), remove(e), remove(index)
一、概述
LinkedList同时实现了List接口和Deque接口,也就是说它既可以看作一个顺序容器,又可以看作一个队列(Queue),同时又可以看作一个栈(Stack)。这样看来,LinkedList简直就是个全能冠军。当你需要使用栈或者队列时,可以考虑使用LinkedList,一方面是因为Java官方已经声明不建议使用Stack类,更遗憾的是,Java里根本没有一个叫做Queue的类(它是个接口名字)。关于栈或队列,现在的首选是ArrayDeque,它有着比LinkedList(当作栈或队列使用时)有着更好的性能。
LinkedList的实现方式决定了所有跟下标相关的操作都是线性时间,而在首段或者末尾删除元素只需要常数时间。为追求效率LinkedList没有实现同步(synchronized),如果需要多个线程并发访问,可以先采用Collections.synchronizedList()
方法对其进行包装。
二、LinkedList实现
底层数据结构
LinkedList底层通过双向链表实现,双向链表的每个节点用内部类Node表示。LinkedList通过first
和last
引用分别指向链表的第一个和最后一个元素。注意这里没有所谓的哑元,当链表为空的时候first
和last
都指向null
。
其中Node是私有的内部类:
构造函数
getFirst(), getLast()
获取第一个元素, 和获取最后一个元素:
removeFirest(), removeLast(), remove(e), remove(index)
remove()
方法也有两个版本,一个是删除跟指定元素相等的第一个元素remove(Object o)
,另一个是删除指定下标处的元素remove(int index)
。
删除元素 - 指的是删除第一次出现的这个元素, 如果没有这个元素,则返回false;判断的依据是equals方法, 如果equals,则直接unlink这个node;由于LinkedList可存放null元素,故也可以删除第一次出现null的元素;
remove(int index)
使用的是下标计数, 只需要判断该index是否有元素即可,如果有则直接unlink这个node。
删除head元素:
删除last元素:
add()
add()方法有两个版本,一个是add(E e)
,该方法在LinkedList的末尾插入元素,因为有last
指向链表末尾,在末尾插入元素的花费是常数时间。只需要简单修改几个相关引用即可;
另一个是add(int index, E element)
,该方法是在指定下表处插入元素,需要先通过线性查找找到具体位置,然后修改相关引用完成插入操作。
add(int index, E element)
, 当index==size时,等同于add(E e); 如果不是,则分两步: 1.先根据index找到要插入的位置,即node(index)方法;2.修改引用,完成插入操作。
上面代码中的node(int index)
函数有一点小小的trick,因为链表双向的,可以从开始往后找,也可以从结尾往前找,具体朝那个方向找取决于条件index < (size >> 1)
,也即是index是靠近前端还是后端。从这里也可以看出,linkedList通过index检索元素的效率没有arrayList高。
addAll()
addAll(index, c) 实现方式并不是直接调用add(index,e)来实现,主要是因为效率的问题,另一个是fail-fast中modCount只会增加1次;
clear()
为了让GC更快可以回收放置的元素,需要将node之间的引用关系赋空。
Positional Access 方法
通过index获取元素
将某个位置的元素重新赋值:
将元素插入到指定index位置:
删除指定位置的元素:
其它位置的方法:
查找操作
查找操作的本质是查找元素的下标:查找第一次出现的index, 如果找不到返回-1;
查找最后一次出现的index, 如果找不到返回-1;
Queue 方法
/**
* Retrieves, but does not remove, the head (first element) of this list.
*
* @return the head of this list, or @code null if this list is empty
* @since 1.5
*/
public E peek()
final Node<E> f = first;
return (f == null) ? null : f.item;
/**
* Retrieves, but does not remove, the head (first element) of this list.
*
* @return the head of this list
* @throws NoSuchElementException if this list is empty
* @since 1.5
*/
public E element()
return getFirst();
/**
* Retrieves and removes the head (first element) of this list.
*
* @return the head of this list, or @code null if this list is empty
* @since 1.5
*/
public E poll()
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f);
/**
* Retrieves and removes the head (first element) of this list.
*
* @return the head of this list
* @throws NoSuchElementException if this list is empty
* @since 1.5
*/
public E remove()
return removeFirst();
/**
* Adds the specified element as the tail (last element) of this list.
*
* @param e the element to add
* @return @code true (as specified by @link Queue#offer)
* @since 1.5
*/
public boolean offer(E e)
return add(e);
Deque 方法
/**
* Inserts the specified element at the front of this list.
*
* @param e the element to insert
* @return @code true (as specified by @link Deque#offerFirst)
* @since 1.6
*/
public boolean offerFirst(E e)
addFirst(e);
return true;
/**
* Inserts the specified element at the end of this list.
*
* @param e the element to insert
* @return @code true (as specified by @link Deque#offerLast)
* @since 1.6
*/
public boolean offerLast(E e)
addLast(e);
return true;
/**
* Retrieves, but does not remove, the first element of this list,
* or returns @code null if this list is empty.
*
* @return the first element of this list, or @code null
* if this list is empty
* @since 1.6
*/
public E peekFirst()
final Node<E> f = first;
return (f == null) ? null : f.item;
/**
* Retrieves, but does not remove, the last element of this list,
* or returns @code null if this list is empty.
*
* @return the last element of this list, or @code null
* if this list is empty
* @since 1.6
*/
public E peekLast()
final Node<E> l = last;
return (l == null) ? null : l.item;
/**
* Retrieves and removes the first element of this list,
* or returns @code null if this list is empty.
*
* @return the first element of this list, or @code null if
* this list is empty
* @since 1.6
*/
public E pollFirst()
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f);
/**
* Retrieves and removes the last element of this list,
* or returns @code null if this list is empty.
*
* @return the last element of this list, or @code null if
* this list is empty
* @since 1.6
*/
public E pollLast()
final Node<E> l = last;
return (l == null) ? null : unlinkLast(l);
/**
* Pushes an element onto the stack represented by this list. In other
* words, inserts the element at the front of this list.
*
* <p>This method is equivalent to @link #addFirst.
*
* @param e the element to push
* @since 1.6
*/
public void push(E e)
addFirst(e);
/**
* Pops an element from the stack represented by this list. In other
* words, removes and returns the first element of this list.
*
* <p>This method is equivalent to @link #removeFirst().
*
* @return the element at the front of this list (which is the top
* of the stack represented by this list)
* @throws NoSuchElementException if this list is empty
* @since 1.6
*/
public E pop()
return removeFirst();
/**
* Removes the first occurrence of the specified element in this
* list (when traversing the list from head to tail). If the list
* does not contain the element, it is unchanged.
*
* @param o element to be removed from this list, if present
* @return @code true if the list contained the specified element
* @since 1.6
*/
public boolean removeFirstOccurrence(Object o)
return remove(o);
/**
* Removes the last occurrence of the specified element in this
* list (when traversing the list from head to tail). If the list
* does not contain the element, it is unchanged.
*
* @param o element to be removed from this list, if present
* @return @code true if the list contained the specified element
* @since 1.6
*/
public boolean removeLastOccurrence(Object o)
if (o == null)
for (Node<E> x = last; x != null; x = x.prev)
if (x.item == null)
unlink(x);
return true;
else
for (Node<E> x = last; x != null; x = x.prev)
if (o.equals(x.item))
unlink(x);
return true;
return false;
系列文章持续更新,微信搜一搜「傲骄鹿先生 」,回复【面试】有准备的一线大厂面试资料。
Java集合框架源码解读——Collection - ArrayList 源码解析
以上是关于Java集合框架源码解读——Collection - LinkedList源码解析的主要内容,如果未能解决你的问题,请参考以下文章
Java集合框架源码解读——Collection - LinkedList源码解析
Java集合框架源码解读——Collection - LinkedList源码解析