LinkedList删除结点源码分析
Posted 似水流年,是谁苍白了等待
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LinkedList删除结点源码分析相关的知识,希望对你有一定的参考价值。
目录
那么LinkedList用来存储数据,那么跟ArrayList有什么区别?
3.LinkedList.remove() 方法;默认删除第一个结点
3)执行unlinkFirst(f), //将f指向的双向链表的第一个结点拿掉
前言
在学习LinkedList之前,我们先需要了解LinkeList是什么?以及它是怎么样实现的等多个知识点;
LinkedList是一种常见的基础数据结构,基于链表,也是一种线性表,但是它的存储并不会按线性的顺序存储数据,在数据结构自考课本中学过,它的存储地址是离散的,可以存在位置不相邻的位置,而且在每一个节点里存到下一个节点的地址。
那么LinkedList用来存储数据,那么跟ArrayList有什么区别?
- linkedlist和arraylist不同,删除或增加元素时,其后边的元素都不需要跟着移动,因为他的地址是可以不连续的。只需要引用前后节点的指针就行。
- linkedlist删除和增加的效率比较高,LinkedList是基于双向链表存储的,当查询对应index位置的数据时,会先计算链表总长度一半的值,判读index是在这个值的左边还是右边,然后决定从头结点还是从尾结点开始遍历;
如图,可以看看源码
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;
}
}
除此之外,LinkedList对内存的占用也是比较大的,毕竟每个Node都维护着前后指向地址的节点,数据量大的话会占用不少内存空间。
因为每存一个元素就需要一个节点,所以这样下来当数据量大的时候node节点也非常大,会占用更多的内存。
LinkedList删除结点是怎么样删除的?
public class Test {
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
linkedList.remove(1);
System.out.println("linkedList"+linkedList);
}
}
根据此代码段分析它删除实现
1、首先了解LinkedList类声明的变量有哪些
全部成员变量说明
//用于标识链表的长度
transient int size = 0;
/**
* Pointer to first node.
* Invariant: (first == null && last == null) ||
* (first.prev == null && first.item != null)
*/
//指向链表的头
transient Node<E> first;
/**
* Pointer to last node.
* Invariant: (first == null && last == null) ||
* (last.next == null && last.item != null)
*/
//指向链表的尾
transient Node<E> last;
2、内部类Node<E>说明
private static class Node<E> {
E item; //item用于保存数据
Node<E> next; //next用于指向当前节点的下一个节点
Node<E> prev; //prev用于指向当前节点的前一个节点
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
3.LinkedList.remove() 方法;默认删除第一个结点
1)执行removeFirst
public E remove() {
return removeFirst();
}
2)执行removeFirst
public E removeFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
}
3)执行unlinkFirst(f), //将f指向的双向链表的第一个结点拿掉
private E unlinkFirst(Node<E> f) {
// assert f == first && f != null;
//获取到将要删除的元素
final E element = f.item;
//将next引用指向下一个节点
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;
}
执行过程详解
- 获取到将要删除的元素(内容)
- 将next引用指向下一个节点
- 当前的元素值为空,意味着删除了传进去的那个节点
- 删除需要删除的节点和下一个结点的引用,让垃圾回收器认为它是个垃圾。
- 将原先的first指向下一个结点
- 判断next是否为空,这里返回false,因此需要走next.prev=null也就是将下一个结点的前驱删掉,此时f结点已经成为一个单独的节点,没有任务引用指向他,就成为了垃圾。
- 链表减一
- 修改记录加一
- 返回删除的元素
以上是关于LinkedList删除结点源码分析的主要内容,如果未能解决你的问题,请参考以下文章