LinkedList源码阅读笔记,刚从阿里、头条面试回来

// 否则把原首节点的prev指针置为新节点

if (f == null)

last = newNode;

else

f.prev = newNode;

//元素个数加1

size++;

// 修改次数 +1,用于 fail-fast 处理

modCount++;

}

public void addFirst(E e) {

linkFirst(e);

}

  • 尾插法

void linkLast(E e) {

//尾结点

final Node l = last;

//新节点

final Node newNode = new Node<>(l, e, null);

//尾结点置为新节点

last = newNode;

//如果链表为空,头结点指向尾结点

if (l == null)

first = newNode;

else

l.next = newNode;

//元素个数加1

size++;

// 修改次数 +1,用于 fail-fast 处理

modCount++;

}

public void addLast(E e) {

linkLast(e);

}

public boolean add(E e) {

linkLast(e);

return true;

}

在链表头部和尾部插入时间复杂度都是O(1),头插法和尾插法的示意图如下:

在这里插入图片描述

  • 中间插入法:中间插入需要找到插入位置节点,改变该节点的前趋和该节点前趋节点的后继

在这里插入图片描述

//根据索引插入节点

public void add(int index, E element) {

//判断是否越界

checkPositionIndex(index);

//未插入

if (index == size)

linkLast(element);

else

//找到索引位置节点,在该节点前插入新节点

linkBefore(element, node(index));

}

// 在节点succ之前添加元素

void linkBefore(E e, Node succ) {

//节点succ的前趋节点

final Node pred = succ.prev;

//新节点

final Node newNode = new Node<>(pred, e, succ);

//改变节点succ的前趋指向

succ.prev = newNode;

// 判断前置节点是否为空

// 如果为空,说明是第一个添加的元素,头结点重新赋值

// 否则修改前置节点的next为新节点

if (pred == null)

first = newNode;

else

pred.next = newNode;

//元素个数加1

size++;

// 修改次数 +1,用于 fail-fast 处理

modCount++;

}

在中间添加元素效率低一些,首先要先找到插入位置的节点,再修改前后节点的指针,时间复杂度为O(n)。

删除元素


双链表中删除元素只需要改变前趋和后继的指向。

  • 删除头节点

//删除头节点

public E removeFirst() {

final Node f = first;

//如果链表为空,抛出异常

if (f == null)

throw new NoSuchElementException();

// 删除首节点

return unlinkFirst(f);

}

// 删除头节点

private E unlinkFirst(Node f) {

// 头结点

final E element = f.item;

//头结点后继节点

final Node next = f.next;

//头结点数据域后继置空,帮助GC

f.item = null;

f.next = null;

//头结点置为后继节点

first = next;

// 如果只有一个元素,删除了,把last也置为空

// 否则把next的前趋置为空

if (next == null)

last = null;

else

next.prev = null;

size–;

modCount++;

//返回删除的节点

return element;

}

  • 删除尾结点

//删除尾结点

public E removeLast() {

//尾结点

final Node l = last;

//链表为空,抛出异常

if (l == null)

throw new NoSuchElementException();

return unlinkLast(l);

}

//删除尾结点

private E unlinkLast(Node l) {

// 尾结点元素

final E element = l.item;

//尾结点前趋节点

final Node prev = l.prev;

//尾结点数据、前趋置为null,帮助GC

l.item = null;

l.prev = null;

//尾结点置为前趋节点

last = prev;

// 如果只有一个元素,删除了把first置为空

// 否则把前置节点的next置为空

if (prev == null)

first = null;

else

prev.next = null;

size–;

modCount++;

//返回删除的节点

return element;

}

注意:

不管是上一节的头插入和未插入,还是这一节的删除头节点和删除尾结点,都没有在List中定义。前面提到,LinkedList实现了Deque接口,所以这是作为双向队列的LinkedList插入和删除元素的方式。还有获取头结点和尾结点的方法getFirst()和getLast(),同样都是双向队列的实现。

  • 删除指定位置的节点

在这里插入图片描述

//删除指定位置的节点

public E remove(int index) {

//检查越界情况

checkElementIndex(index);

//根据索引找到节点,删除

return unlink(node(index));

}

//删除指定节点

E unlink(Node x) {

// 删除节点的值

final E element = x.item;

//被删除节点的后继节点

final Node next = x.next;

//被删除节点的前趋节点

final Node prev = x.prev;

// 如果前趋节点为空

// 说明是首节点,让first指向x的后继节点

// 否则修改前置节点的next为x的后继节点

if (prev == null) {

first = next;

} else {

prev.next = next;

x.prev = null;

}

// 如果后继节点为空

// 说明是尾节点,让last指向x的前趋节点

// 否则修改后置节点的prev为x的前趋节点

if (next == null) {

last = prev;

} else {

next.prev = prev;

x.next = null;

}

// 清空x的元素值,协助GC

x.item = null;

// 元素个数减1

size–;

// 修改次数加1,fail-fast

modCount++;

//返回删除的元素

return element;

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

最后

文章中涉及到的知识点我都已经整理成了资料,录制了视频供大家下载学习,诚意满满,希望可以帮助在这个行业发展的朋友,在论坛博客等地方少花些时间找资料,把有限的时间,真正花在学习上,所以我把这些资料,分享出来。相信对于已经工作和遇到技术瓶颈的朋友们,在这份资料中一定都有你需要的内容。

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img

盖了95%以上Java开发知识点,真正体系化!**

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-M84I33KD-1712654952514)]

最后

文章中涉及到的知识点我都已经整理成了资料,录制了视频供大家下载学习,诚意满满,希望可以帮助在这个行业发展的朋友,在论坛博客等地方少花些时间找资料,把有限的时间,真正花在学习上,所以我把这些资料,分享出来。相信对于已经工作和遇到技术瓶颈的朋友们,在这份资料中一定都有你需要的内容。

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-rLFPsYZa-1712654952514)]

  • 14
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LinkedList是一种基于双向链表的List数据结构。它的内部实现源于对链表的操作,所以适用于频繁增加和删除元素的情况。LinkedList的创建可以通过构造器来完成,而往LinkedList中添加对象可以使用add方法。LinkedList不是线程安全的,并且查询元素的效率相对较低,因为需要一个一个遍历链表来查找元素。LinkedList实现了Queue接口,所以它既可以作为队列使用,也可以作为栈使用。此外,LinkedList还实现了Deque接口,即双端队列。与ArrayList相比,LinkedList的内部结构有所不同,LinkedList继承自AbstractSequentialList,然后再继承自AbstractList。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [第三章 LinkedList源码解析1](https://download.csdn.net/download/weixin_35760849/86324281)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [LinkedList源码解析](https://blog.csdn.net/qq_38826019/article/details/115677359)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值