最后
一次偶然,从朋友那里得到一份“java高分面试指南”,里面涵盖了25个分类的面试题以及详细的解析:JavaOOP、Java集合/泛型、Java中的IO与NIO、Java反射、Java序列化、Java注解、多线程&并发、JVM、Mysql、Redis、Memcached、MongoDB、Spring、Spring Boot、Spring Cloud、RabbitMQ、Dubbo 、MyBatis 、ZooKeeper 、数据结构、算法、Elasticsearch 、Kafka 、微服务、Linux。
这不,马上就要到招聘季了,很多朋友又开始准备“金三银四”的春招啦,那我想这份“java高分面试指南”应该起到不小的作用,所以今天想给大家分享一下。
请注意:关于这份“java高分面试指南”,每一个方向专题(25个)的题目这里几乎都会列举,在不看答案的情况下,大家可以自行测试一下水平 且由于篇幅原因,这边无法展示所有完整的答案解析
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;
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;
}
5. void addFirst(E e) —— 在链表的起始端插入元素。
public void addFirst(E e) {
//调用另外一个方法
linkFirst(e);
}
private void linkFirst(E e) {
//获取链表原来第一个节点
final Node f = first;
//新建一个节点(这个就是链表未来的第一个节点)
final Node newNode = new Node<>(null, e, f);
//将新建的这个节点赋值给fist(更新记录)
first = newNode;
//如果当前的链表是空的,则这个也是最后一个节点
if (f == null)
last = newNode;
//否则,将原来的第一个节点变成第二个节点
else
f.prev = newNode;
//修改长度和计数器
size++;
modCount++;
}
6. void addLast(E e) —— 在链表的末尾添加元素。
public void addLast(E e) {
//调用另外一个方法
linkLast(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;
//修改长度与计数器
size++;
modCount++;
}
二、获取与修改元素的方法
1. E get(int i) —— 获取某个位置上的元素
public E get(int index) {
//检测参数是否合法(是否越界)
checkElementIndex(index);
//返回这个节点的item属性,node(index)返回的是index位置的这个节点
return node(index).item;
}
2. E set(int i,E e) —— 修改某个位置上的元素,结果返回这个位置上原来的值。
public E set(int index, E element) {
//参数是否合法
checkElementIndex(index);
最后如何让自己一步步成为技术专家
说句实话,如果一个打工人不想提升自己,那便没有工作的意义,毕竟大家也没有到养老的年龄。
当你的技术在一步步贴近阿里p7水平的时候,毫无疑问你的薪资肯定会涨,同时你能学到更多更深的技术,交结到更厉害的大牛。
推荐一份Java架构之路必备的学习笔记,内容相当全面!!!
成年人的世界没有容易二字,前段时间刷抖音看到一个程序员连着加班两星期到半夜2点的视频。在这个行业若想要拿高薪除了提高硬实力别无他法。
你知道吗?现在有的应届生实习薪资都已经赶超开发5年的程序员了,实习薪资26K,30K,你没有紧迫感吗?做了这么多年还不如一个应届生,真的非常尴尬!
进了这个行业就不要把没时间学习当借口,这个行业就是要不断学习,不然就只能被裁员。所以,抓紧时间投资自己,多学点技术,眼前困难,往后轻松!
【关注】+【转发】+【点赞】支持我!创作不易!
你能学到更多更深的技术,交结到更厉害的大牛。
推荐一份Java架构之路必备的学习笔记,内容相当全面!!!
[外链图片转存中…(img-9FSeKFvP-1714999581403)]
成年人的世界没有容易二字,前段时间刷抖音看到一个程序员连着加班两星期到半夜2点的视频。在这个行业若想要拿高薪除了提高硬实力别无他法。
你知道吗?现在有的应届生实习薪资都已经赶超开发5年的程序员了,实习薪资26K,30K,你没有紧迫感吗?做了这么多年还不如一个应届生,真的非常尴尬!
进了这个行业就不要把没时间学习当借口,这个行业就是要不断学习,不然就只能被裁员。所以,抓紧时间投资自己,多学点技术,眼前困难,往后轻松!
【关注】+【转发】+【点赞】支持我!创作不易!