public class LinkedList
extends AbstractSequentialList
implements List, Deque, Cloneable, java.io.Serializable
继承了 AbstractSequentialList ,提供了 List 接口的骨干实现,从而最大限度减少了实现“连续访问”数据存储支持的此接口所需的工作,从而减少实现 List 的复杂度。
LinkedList 的主要属性
================
//代表LinkedList的长度
transient int size = 0;
//第一个元素
transient Node first;
//最后一个元素
transient Node last;
上面的 Node 是一个内部类,它就是双向链表上的节点。
内部类
===
private static class Node {
//当前节点保存的元素
E item;
//当前节点的下一个节点
Node next;
//当前节点的上一个节点
Node prev;
//构造器
Node(Node prev, E element, Node next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
构造器
===
在 LinkedList 中,提供了两个构造器,分别是空参构造器和带有集合参数的构造器。
1. 空参构造器
空参的构造器真的是空的,哈哈哈
public LinkedList() {}
2. 带有集合参数的构造器
public LinkedList(Collection<? extends E> c) {
//调用空参构造器
this();
//将参数集合中所有的元素作为初始化集合的元素,具体看下面的分析
addAll©;
}
public boolean addAll(Collection<? extends E> c) {
//调用的是下面的重载方法
return addAll(size, c);
}
public boolean addAll(int index, Collection<? extends E> c) {
//检查index是否越界
checkPositionIndex(index);
//将参数集合转化为数组
Object[] a = c.toArray();
//获取转化后数组的长度
int numNew = a.length;
//如果数组长度为0,则直接返回false
if (numNew == 0)
return false;
//定义两个节点
Node pred, succ;
//如果添加的索引位置index与元素的个数相同,则将succ置为null,将pred置为最后一个节点
if (index == size) {
succ = null;
pred = last;
} else {
//否则,succ置为index位置的节点;pred置为succ.prev
succ = node(index);
pred = succ.prev;
}
//遍历数组
for (Object o : a) {
@SuppressWarnings(“unchecked”) E e = (E) o;
Node 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;
}
private void checkPositionIndex(int index) {
if (!isPositionIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private boolean isPositionIndex(int index) {
return index >= 0 && index <= size;
}
上面的这一大堆逻辑实际上就是将参数集合中的所有元素作为初始化 LinkedList 的元素。
常用的方法
=====
一、添加元素的方法
在 LinkedList 中,提供了 6 个用于添加元素的方法。
1. boolean add(E e) —— 向集合的末尾添加元素,结果返回布尔值,表示操作是否成功。
public boolean add(E e) {
//调用了下面的方法
linkLast(e);
return true;
}
void linkLast(E e) {
//获取双向链表的最后一个元素
final Node l = last;
//新建一个节点,这个节点的上一个节点的值为原来的链表最后的一个节点的的值;下一个节点为null
final Node newNode = new Node<>(l, e, null);
//记录最新的最后一个节点
last = newNode;
//如果原链表的最后一个节点为null,则新创建的节点就是第一个节点;否则,就将原来最后一个节点的下一个节点的引用改为新创建的节点
if (l == null)
first = newNode;
else
l.next = newNode;
//改变长度与计数器
size++;
modCount++;
}
2. void add(int index,E element) —— 在链表的某个位置插入元素
public void add(int index, E element) {
//检查索引是否越界
checkPositionIndex(index);
//如果要插入的位置是链表的末尾,则调用上面分析过的方法;否则调用linkBefore,具体看后面分析
if (index == size)
linkLast(element);
else
linkBefore(element, node(index));
}
void linkBefore(E e, Node succ) {//参数element是待添加的元素;succ是插入位置的节点
//获取待插入位置节点的上一个节点的引用
final Node pred = succ.prev;
//创建一个新的节点
final Node newNode = new Node<>(pred, e, succ);
succ.prev = newNode;
//如果插入的位置是链表的起始端,则需要将该节点赋值给first记录
if (pred == null)
first = newNode;
else
//否则,将原来这个位置上的节点的下一个节点的引用修改为该节点引用
pred.next = newNode;
//修改长度与计数器
size++;
modCount++;
}
3. boolean addAll(Collection<? extend E> 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;
//如果数组长度为0,则直接返回false
if (numNew == 0)
return false;
//声明两个节点
Node pred, succ;
//如果待插入位置就是链表的末尾,则将succ置为null;pred就是最后一个节点
if (index == size) {
succ = null;
pred = last;
} else {
succ = node(index);
pred = succ.prev;
}
//细看这个方法其实跟带参构造器是相似的,上面已经分析过了,这里就省略了。
for (Object o : a) {
@SuppressWarnings(“unchecked”) E e = (E) o;
小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:前端)
前端框架
前端框架太多了,真的学不动了,别慌,其实对于前端的三大马车,Angular、React、Vue 只要把其中一种框架学明白,底层原理实现,其他两个学起来不会很吃力,这也取决于你以后就职的公司要求你会哪一个框架了,当然,会的越多越好,但是往往每个人的时间是有限的,对于自学的学生,或者即将面试找工作的人,当然要选择一门框架深挖原理。
以 Vue 为例,我整理了如下的面试题。
nuIkIJ4-1710605085325)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:前端)
[外链图片转存中…(img-e1s6JjMa-1710605085326)]
前端框架
前端框架太多了,真的学不动了,别慌,其实对于前端的三大马车,Angular、React、Vue 只要把其中一种框架学明白,底层原理实现,其他两个学起来不会很吃力,这也取决于你以后就职的公司要求你会哪一个框架了,当然,会的越多越好,但是往往每个人的时间是有限的,对于自学的学生,或者即将面试找工作的人,当然要选择一门框架深挖原理。
以 Vue 为例,我整理了如下的面试题。