LinkedList与ArrayList都是List接口的具体实现类。LinkedList与ArrayList在功能上也是大体一致,但是因为两者具体的实现方式不一致,所以在进行一些相同操作的时候,其效率也是有差别的。

对于抽象的数据结构——线性表而言,线性表分为两种,一种是顺序存储结构的顺序表,另一种是通过指针来描述其逻辑位置的链表。
针对于具体的Java实现:
针对插入与删除操作,ArrayList每插入一个元素,首先需要判断数组的空间够不够,不够要进行扩容,在有足够的空间的基础上,在指定的index位置上插入元素,但是该index及以后的元素都要后移。虽然删除操作不需要判断空间够不够,但同样需要该index及以后的元素向前移动,这些移动的操作会增加时间的复杂度。但是对于LinkedList就不一样,因为使用指针来指示其逻辑的位置,所以插入与删除的操作的时间复杂度都是 ** O(1) **
虽然对于ArrayList而言,插入与删除的时间复杂度很高,但是对于查找指定位置的元素这种操作而言,就非常的快,因为可以通过数组直接得到该下标对应的元素。反而,LinkedList而言,无法直接返回指定位置的元素,需要一个个查询,其时间的复杂度就是 ** O(n) **
与如何实现Java的ArrayList经典实体类一样,实现的目的主要在于练手以及掌握官方实现的原理和一些技巧,因此很多需要与其他类配合的方法和功能,就先不在这里实现如iterator等
所以,实现的LinkedList的方法如下:
add方法
get方法
indexOf方法
remove方法
与实现ArrayList的名字一样,为SimpleLinkedList。源码地址,欢迎star,fork
构建一个双向链表
构建的代码如下:
private static class Node<E>{
E item;
Node<E> next;
Node<E> prev;
public Node(E item, Node<E> next, Node<E> prev) {
this.item = item;
this.next = next;
this.prev = prev;
}
}
常规的双向链表的构建方法,一个数字域存放数组,一个前指针指向一个Node类型的元素,一个后指针指向一个Node类型的元素。
对于LinkedList的实现而言,还需要以下三个成员变量
private int size; private Node<E> first; private Node<E> last;
Add方法
这里实现的add方法是简单的add(E e)以及add(int index,E e)两个方法,addAll()将其他集合转换LinkedList的方法,暂时放到以后去实现。
add方法两个重载方法,其分别对应不同的添加方式。先说add(E e)方法的实现。
public boolean add(E element) {
addAtLast(element);
return true;
}
不指定位置添加元素,则默认添加到了链表的最后。addAtLast的核心代码如下:
private void addAtLast(E element) {
Node<E> l = last;
Node<E> node = new Node<E>(element, null, l);
last = node;
if (l == null) {
first = node;
} else {
l.next = node;
}
size++;
}
首先找到最后一位的Node元素,然后根据element创建一个新的Node元素,其next指向为null,prev指向为最后一位Node元素。在创建完Node元素之后,last就变成了先创建的Node元素,接下来只需要把新node元素加到链表中即可。即让l对象(原最后一位,现倒数第二位元素的next指针,指向新node元素)。至此,新node元素的next指向null,prev指向倒数第二个元素,倒数第二个元素的next指向新node,就将node成功加入链表。
上述的操作也可以看出,其插入的操作非常省时间,比起ArrayList,扩容,移动元素快很多。
add的第二个重载方法 add(int index ,E e),先看代码实现:
public void add(int index, E element) {
checkRangeForAdd(index);
if (index == size) {
addAtLast(element);
} else {
Node<E> l = node(index);
addBeforeNode(element, l);
}
}
首先判断要插入的index是否在范围内,在的话,再执行后续的add操作。如果要插入的index刚好是最后一位,则执行上面讲的addAtLast,如果不是,则得到index所对应的Node元素,执行addBeforeNode。
获取index所对应的Node元素,是node方法,代码如下:
private Node<E> node(int index) {
if (index < (size << 1)) {
Node<E> cursor = first;
for (int i = 0; i < index; i++) {
cursor = cursor.next;
}
return cursor;
} else {
Node<E> cursor = last;
for (int i = size - 1; i > index; i--) {
cursor = cursor.prev;
}
return cursor;
}
}
这里的查找采用二分查找,节省查找时间,而且也应用到了双向链表的特点。首先判断index在前一半的范围内,还是后一半的范围内。如果是前一半,则游标Node初始为first,用游标Node元素的next,不断指向index所在的元素。如果是后一半,则游标Node初始为last,用游标Node元素的prev,不断指向index所在的元素。
在指定元素的前面插入新节点的addBeforeNode的方法如下:
private void addBeforeNode(E element, Node<E> specifiedNode) {
Node<E> preNode = specifiedNode.prev;
Node<E> newNode = new Node<>(element, specifiedNode, preNode);
if (preNode == null) {
first = newNode;
} else {
preNode.next = newNode;
}
specifiedNode.prev = newNode;
size++;
}
插入的方式很简单,新节点的prev是原index元素的prev,新节点的next是原index元素。剩下的操作是把该node放到链表中,让原index元素的prev的next为新节点,但是要判断preNode是不是空,是的话,表示newNode为第一个元素,就是first。
至此,一个add方法,就实现完了。
get方法
get方法在有了上述node方法之后,就非常的简单。代码如下:
public E get(int index) {
checkRange(index);
return node(index).item;
}
checkRange检查index是否不在范围内。
private void checkRange(int index) {
if (index >= size || index < 0) {
throw new IndexOutOfBoundsException("指定index超过界限");
}
}
indexOf方法
indexOf(Object o)用来得到指定元素的下标。
public int indexOf(Object element) {
Node<E> cursor = first;
int count = 0;
while (cursor != null) {
if (element != null) {
if (element.equals(cursor.item)) {
return count;
}
}else{
if (cursor.item == null) {
return count;
}
}
count ++;
cursor = cursor.next;
}
return -1;
}
与ArrayList一样,从第一位开始查找,首先先判断element是不是null,分成两种情况。
remove方法
remove方法与add方法一样,同样有两个重载的方法,remove(Object o)与remove(int index)
先看简单的remove(int index)方法,代码如下:
public E remove(int index) {
checkRange(index);
return deleteLink(index);
}
deleteLink是将该index所对应的节点的链接删除的方法,其代码如下:
private E deleteLink(int index) {
Node<E> l = node(index);
E item = l.item;
Node<E> prevNode = l.prev;
Node<E> nextNode = l.next;
if (prevNode == null) {
first = nextNode;
}else{
prevNode.next = nextNode;
l.next = null;
}
if (nextNode == null) {
last = prevNode;
}else{
nextNode.prev = prevNode;
l.prev = null;
}
size--;
l.item = null;
return item;
}
首先获得该index对应的Node元素,得到该Node元素的前一个元素和后一个元素。接下来,只需要将前一个元素和后一个元素直接相连即可,其他只需要额外判断前一个元素和后一个元素是否为null就行。在判断前一个元素是否为null的时候,只需要操作前一个元素,在判断后一个元素是否为null的时候,也只需要操作后一个元素。最后,将要删除的元素各个引用至为null。
remove另一个重载方法remove(Object o),在实现了indexOf和deleteLink方法之后,就非常简单。
public boolean remove(Object o) {
int index = indexOf(o);
if (index < 0){
return false;
}
deleteLink(index);
return true;
}
获取该元素对应对应的下标,然后执行deleteLink方法,完成remove操作。
总结
至此,一个功能简单的LinkedList就实现完成了,全部的代码可以看源码地址,
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!
# java
# LinkedList
# Java中集合LinkedList的原理与使用方法
# Java LinkedList的实现原理图文详解
# Java集合系列之LinkedList源码分析
# java 集合之实现类ArrayList和LinkedList的方法
# java LinkedList的实例详解
# Java中LinkedList详解和使用示例_动力节点Java学院整理
# Java LinkedList集合功能实例解析
# 链表
# 只需要
# 第二个
# 都是
# 两种
# 所对应
# 先看
# 到该
# 方法如下
# 够不够
# 是有
# 第一个
# 都要
# 不需要
# 就不
# 基础上
# 线性表
# 只需
# 很高
# 数据结构
相关文章:
定制建站策划方案_专业建站与网站建设方案一站式指南
学校建站服务器如何选型才能满足性能需求?
c++ stringstream用法详解_c++字符串与数字转换利器
c# Task.Yield 的作用是什么 它和Task.Delay(1)有区别吗
青岛网站建设如何选择本地服务器?
建站与域名管理如何高效结合?
胶州企业网站制作公司,青岛石头网络科技有限公司怎么样?
深圳 网站制作,深圳招聘网站哪个比较好一点啊?
广东专业制作网站有哪些,广东省能源集团有限公司官网?
如何在万网主机上快速搭建网站?
如何通过远程VPS快速搭建个人网站?
建站主机如何选?高性价比方案全解析
浅析上传头像示例及其注意事项
网站制作需要会哪些技术,建立一个网站要花费多少?
如何在Golang中处理模块冲突_解决依赖版本不兼容问题
Thinkphp 中 distinct 的用法解析
建站之星如何助力网站排名飙升?揭秘高效技巧
c# 在高并发下使用反射发射(Reflection.Emit)的性能
建站之星展会模版如何一键下载生成?
如何通过PHP快速构建高效问答网站功能?
西安制作网站公司有哪些,西安货运司机用的最多的app或者网站是什么?
微课制作网站有哪些,微课网怎么进?
如何高效完成独享虚拟主机建站?
交易网站制作流程,我想开通一个网站,注册一个交易网址,需要那些手续?
如何在建站宝盒中设置产品搜索功能?
北京制作网站的公司排名,北京三快科技有限公司是做什么?北京三快科技?
黑客入侵网站服务器的常见手法有哪些?
网站专业制作公司有哪些,做一个公司网站要多少钱?
巅云智能建站系统:可视化拖拽+多端适配+免费模板一键生成
香港服务器网站卡顿?如何解决网络延迟与负载问题?
如何在新浪SAE免费搭建个人博客?
建站之星展会模板:智能建站与自助搭建高效解决方案
建站VPS推荐:2025年高性能服务器配置指南
如何用低价快速搭建高质量网站?
建站之星24小时客服电话如何获取?
企业网站制作公司网页,推荐几家专业的天津网站制作公司?
成都品牌网站制作公司,成都营业执照年报网上怎么办理?
如何在IIS7中新建站点?详细步骤解析
如何快速生成ASP一键建站模板并优化安全性?
如何正确下载安装西数主机建站助手?
如何用腾讯建站主机快速创建免费网站?
盘锦网站制作公司,盘锦大洼有多少5G网站?
网站制作怎么样才能赚钱,用自己的电脑做服务器架设网站有什么利弊,能赚钱吗?
如何挑选优质建站一级代理提升网站排名?
如何用5美元大硬盘VPS安全高效搭建个人网站?
c# 服务器GC和工作站GC的区别和设置
湖州网站制作公司有哪些,浙江中蓝新能源公司官网?
如何有效防御Web建站篡改攻击?
广州美橙建站如何快速搭建多端合一网站?
如何在腾讯云免费申请建站?
*请认真填写需求信息,我们会在24小时内与您取得联系。