LinkedList源码分析
时间:2022-07-23
本文章向大家介绍LinkedList源码分析,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
重要属性
// 存储结点个数
transient int size = 0;
// 指向链表的开头结点
transient Node<E> first;
// 指向链表的最后一个结点,开始时first和last都为空
transient Node<E> last;
Node结点
private static class Node<E> {
E item; // 元素值
Node<E> next; // 下一个结点
Node<E> prev; // 上一个结点
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
在头部添加结点
private void linkFirst(E e) {
// f为旧头
final Node<E> f = first;
// 新建结点prev=null,next=f,作为链表的头
final Node<E> newNode = new Node<>(null, e, f);
// first指向新头
first = newNode;
// 如果插入前为是空链表,则last也指向头,否者将旧头的prev指向新头
if (f == null)
last = newNode;
else
f.prev = newNode;
size++;
modCount++;
}
在尾部添加结点
void linkLast(E e) {
// l为旧尾
final Node<E> l = last;
// 新尾的prev指向旧尾,next指向null
final Node<E> newNode = new Node<>(l, e, null);
// last指向新尾
last = newNode;
// 如果插入前是空链表,则first也指向新尾,否者将旧尾的next指向新尾
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
查询索引为index的元素,索引从0开始
Node<E> node(int 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;
}
}
ArrayList与LinkedList的异同
底层数据结构的不同:ArrayList底层是数组实现的,LinkedList是双向链表实现的,这延伸到数组和链表的区别
在内存中数组是连续的,而链表是不连续的,正是这个底层实现的不同,导致了一下几点不同
- 数组支持随机查找,查找效率高,增加删除的时候需要移动元素,效率低,链表不支持随机查找,查找效率低,增加删除的时候改变指针的指向即可,效率高
- 存储同样的元素时链表用的空间比较大,因为还额外存了下一个元素的指针
添加元素的时候:ArrayList需要考虑扩容,而LinkedList则不需要,因为ArrayList底层是用数组实现的,需要连续的一块空间,当ArrayList扩容时,它需要新开辟一块内存空间,在把原来的数据拷贝到新数组中去,而LinkedList而不用考虑,链表的结点是离散的,不要求连续,所以链表可以分布在内存中任一角落
内存使用:ArrayList不用存指针,在存储相同数量的元素的时候,需要的内存空间更低。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 用Python做一个游戏辅助脚本,完整编程思路分享!
- python获取百度热榜链接的实例方法
- 多图+代码 | 详解Python操作Excel神器openpyxl的各种操作!
- 为了给女朋友独特的七夕惊喜,我学会了人像美肤算法!
- Docker入门笔记总结
- AWVS13破解版安装
- Sqlmap注入使用技巧总结
- Lyft 宣布开源基础设施工具管理平台 Clutch!
- 从库mysqldump会导致复制中断
- DBA的福音,SQL审核利器-goinception
- 前端组件设计原则
- 分析网页 JavaScript Bundles 的几种方法
- 使用 DevTools 新增的 Issues 选项卡发现网页问题
- OpenCV绘制标记函数drawMarker()
- 【crossbeam系列】3 crossbeam-deque:work-stealing算法