Java LinkedList双向链表源码分析

LinkedList就传说中的双向链表了。是List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾 get、remove 和 insert 元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。

查看LinkedList的构造函数:
/*** Constructs an empty list.*/public LinkedList() {header.next = header.previous = header;
}

这里的header变量的定义如下:

private transient Entry<E> header = new Entry<E>(null, null, null);

表示双向循环链表的头结点。其中的Entry定义了双向链表的结构:

private static class Entry<E> {E element;Entry<E> next;Entry<E> previous;Entry(E element, Entry<E> next, Entry<E> previous) {this.element = element;this.next = next;this.previous = previous;}
}

Entry中包括数据元素、前续结点和后续结点。

构造函数即是初始化一个只包含header头结点一个元素的双向链表。

可以得出:LinkedList实质上就是一个双向链表,并把header作为头结点。
查看LinkedList的add(E)方法:
public boolean add(E e) {addBefore(e, header);return true;
}

add(E)方法主要指向了addBefore(E, Entry)函数:

private Entry<E> addBefore(E e, Entry<E> entry) {Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);newEntry.previous.next = newEntry;newEntry.next.previous = newEntry;size++;modCount++;return newEntry;
}

这个方法中传入的第二个参数entry为header头结点,表示把元素插入到header头结点之前。然后后两句分别表示设置前续结点的后续结点和后续结点的前续结点。以便连接成双向链表。

可以得出:LinkedList的add(E)方法把新结点插入到header头结点之前,即列表的结尾。
查看LinkedList的set(int, E)方法:
/*** Replaces the element at the specified position in this list with the* specified element.** @param index index of the element to replace* @param element element to be stored at the specified position* @return the element previously at the specified position* @throws IndexOutOfBoundsException {@inheritDoc}*/public E set(int index, E element) {Entry<E> e = entry(index);E oldVal = e.element;e.element = element;return oldVal;
}

这个函数主要是设置某个索引位置的结点。首先调用了entry(int)方法:

/*** Returns the indexed entry.*/private Entry<E> entry(int index) {if (index < 0 || index >= size)throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);Entry<E> e = header;if (index < (size >> 1)) {for (int i = 0; i <= index; i++)e = e.next;} else {for (int i = size; i > index; i--)e = e.previous;}return e;
}

这里首先判断需要设置的位置是否越界,如果越界则抛出异常。然后通过循环找到需要替换的结点。

接下来回到set(int ,E)函数,把旧的结点替换成新的结点,并返回旧的结点。

可以得出:set(int ,E)方法需要循环遍历链表,时间开销比较大。
查看LinkedList的push(E)方法:
/*** Pushes an element onto the stack represented by this list.  In other* words, inserts the element at the front of this list.** <p>This method is equivalent to {@link #addFirst}.** @param e the element to push* @since 1.6*/public void push(E e) {addFirst(e);
}

push(E)方法主要调用了addFirst(E)方法:

/*** Inserts the specified element at the beginning of this list.** @param e the element to add*/public void addFirst(E e) {addBefore(e, header.next);
}

这里继续调用addBefore(E, Entity)表示把新节点插入到header头结点之后。

可以得出:push(E)方法主要是把新节点插入到header头结点之后。
查看LinkedList的pop()方法:
/*** Pops an element from the stack represented by this list.  In other* words, removes and returns the first element of this list.** <p>This method is equivalent to {@link #removeFirst()}.** @return the element at the front of this list (which is the top*         of the stack represented by this list)* @throws NoSuchElementException if this list is empty* @since 1.6*/public E pop() {return removeFirst();
}

这里继续调用了removeFirst()方法:

/*** Removes and returns the first element from this list.** @return the first element from this list* @throws NoSuchElementException if this list is empty*/public E removeFirst() {return remove(header.next);
}

这里继续调用remove(Entry<E>)方法:

/*** Retrieves and removes the head (first element) of this list.** @return the head of this list* @throws NoSuchElementException if this list is empty* @since 1.5*/private E remove(Entry<E> e) {if (e == header)throw new NoSuchElementException();E result = e.element;e.previous.next = e.next;e.next.previous = e.previous;e.next = e.previous = null;e.element = null;size--;modCount++;return result;
}

在调用remove(Entry<E>)方法时,传入了header的下一个结点。如果传入的下一个结点是header的话,表示此事链表中只有一个结点header,此时抛出异常。如果找到则删除该节点(注意这里双向链表删除结点时的步骤),并返回被删除的结点。

可以得出:pop()方法删除的是header头结点之后的结点,并返回被删除的结点。
★ LinkedList实质上就是一个双向链表,并把header作为头结点。
★ LinkedList的add(E)方法把新结点插入到header头结点之前。
★ set(int ,E)方法需要循环遍历链表,时间开销比较大。
★ push(E)方法主要是把新节点插入到header结点之前
★ pop()方法删除的是header头结点之后的结点,并返回被删除的结点。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/312905.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

容器日志管理 (2) 开源日志管理方案 ELK/EFK

本篇已加入《.NET Core on K8S学习实践系列文章索引》&#xff0c;可以点击查看更多容器化技术相关系列文章。上一篇《容器日志管理&#xff08;1&#xff09;》中介绍了Docker自带的logs子命令以及其Logging driver&#xff0c;本篇将会介绍一个流行的开源日志管理方案ELK/EFK…

Java ArrayList、LinkedList和Vector的使用及性能分析

第1部分 List概括 List 是一个接口&#xff0c;它继承于Collection的接口。它代表着有序的队列。 AbstractList 是一个抽象类&#xff0c;它继承于AbstractCollection。AbstractList实现List接口中除size()、get(int location)之外的函数。 AbstractSequentialList 是一个抽象类…

关于Scrum起源,读这一篇论文就足够啦!《新新产品开发游戏》

关于Scrum的起源&#xff0c;我们经常会提到1986年发表在HBR上的一篇论文&#xff0c;《The New New Product Development Game》&#xff0c;今天我们把它重新翻译&#xff0c;一起重温为何Scrum会如此设置3355&#xff1f;为何会用橄榄球的术语来代表Scrum&#xff1f;The Ne…

Java HashMap的实现原理详解

HashMap是Java Map类型的集合类中最常使用的&#xff0c;本文基于Java1.8&#xff0c;对于HashMap的实现原理做一下详细讲解。 &#xff08;Java1.8源码&#xff1a;http://docs.oracle.com/javase/8/docs/api/&#xff09; 一、HashMap实现原理总结 HashMap的实现原理总结如下…

ASP.NET Core快速入门(第5章:认证与授权)--学习笔记

点击蓝字关注我们课程链接&#xff1a;http://video.jessetalk.cn/course/explore良心课程&#xff0c;大家一起来学习哈&#xff01;任务31&#xff1a;课时介绍1.Cookie-based认证与授权2.Cookie-based认证实现3.Jwt认证与授权介绍4.Jwt认证与授权实现5.Jwt认证与授权6.Role …

Java HashSet的实现原理详解

HashSet是Java Map类型的集合类中最常使用的&#xff0c;本文基于Java1.8&#xff0c;对于HashSet的实现原理做一下详细讲解。 &#xff08;Java1.8源码&#xff1a;http://docs.oracle.com/javase/8/docs/api/&#xff09; 一、HashSet实现原理总结 HashSet的实现原理总结如下…

asp.net mvc 自定义 pager 封装与优化

asp.net mvc 自定义 pager 封装与优化Intro之前做了一个通用的分页组件&#xff0c;但是有些不足&#xff0c;从翻页事件和分页样式都融合在后台代码中&#xff0c;到翻页事件可以自定义&#xff0c;再到翻页和样式都和代码分离&#xff0c; 自定义分页 pager 越来越容易扩展了…

Java LinkedHashMap的实现原理详解

1. LinkedHashSet概述&#xff1a; LinkedHashSet是具有可预知迭代顺序的Set接口的哈希表和链接列表实现。此实现与HashSet的不同之处在于&#xff0c;后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序&#xff0c;该迭代顺序可为插入顺序或是访问顺序…

.net core 中通过 PostConfigure 验证 Options 参数

.net core 中通过 PostConfigure 验证 Options 参数Intro在 .net core 中配置项推荐用 Options 来实现&#xff0c;有一些参数可能必须是用由用户来配置&#xff0c;不能直接写成默认值的参数&#xff0c;这样就需要就 Options 中的参数做一些校验&#xff0c;否则程序内部可能…

Spring配置错误java.lang.NoClassDefFoundError: org/springframework/jdbc/datasource/TransactionAwareDataS

在对Spring数据源dataSource配置之后&#xff0c;运行程序出现如下错误&#xff1a; java.lang.NoClassDefFoundError: org/springframework/jdbc/datasource/TransactionAwareDataSourceProxy 原因是项目没有导入spring-jdbc的jar包。 如果使用maven&#xff0c;可以直接在pom…

.NET做人脸识别并分类

前言在游乐场、玻璃天桥、滑雪场等娱乐场所&#xff0c;经常能看到有摄影师在拍照片&#xff0c;令这些经营者发愁的一件事就是照片太多了&#xff0c;客户在成千上万张照片中找到自己可不是件容易的事。在一次游玩等活动或家庭聚会也同理&#xff0c;太多了照片导致挑选十分困…

Java连接Mysql数据库警告:Establishing SSL connection without server's identity verification is not recommend

Java使用mysql-jdbc连接MySQL出现如下警告&#xff1a; Establishing SSL connection without servers identity verification is not recommended. According to MySQL 5.5.45, 5.6.26 and 5.7.6 requirements SSL connection must be established by default if explicit opt…

.NET Core 3.0中用 Code-First 方式创建 gRPC 服务与客户端

.NET Core ❤ gRPC千呼万唤的 .NET Core 3.0 终于在 9 月份正式发布&#xff0c;在它的众多新特性中&#xff0c;除了性能得到了大大提高&#xff0c;比较受关注的应该是 ASP.NET Core 3.0 对 gRPC 的集成了。它的源码托管在 grpc-dotnet 这个 Github 库中&#xff0c;由微软 .…

Spring集成Mybatis错误Result Maps collection already contains value for XXX

Spring在集成Mybatis出现如下错误&#xff1a; SpringResult Maps collection already contains value for com.guowei.maven.framework.dao.UserMapper.resultUser at org.mybatis.spring.SqlSessionFactoryBean.buildSqlSessionFactory(SqlSessionFactoryBean.java:468) at o…

dotnet Blazor 用 C# 控制界面行为

微软很久就在做 Blazor 但是我现在才开始创建一个测试项目&#xff0c;我想用 C# 去控制 HTML 界面。小伙伴也许会问现在前端不是烂大街么&#xff0c;为什么还需要 Blazor 来做。可能原因只有一个&#xff0c;就是可以使用 C# 写脚本&#xff0c;代码比较清真用 VisualStudio …

Spring集成Mybatis配置映射文件方法详解

Spring ORM模块集成Mybatis使用到了mybatis-spring&#xff0c;在配置mybatis映射文件的时候&#xff0c;一般不直接在Mybatis的配置文件里进行配置&#xff0c;而会在Spring的配置文件里使用MapperScannerConfigurer来配置。MapperScannerConfigurer会自动扫描basePackage指定…

2019年该学习哪门语言?建议学习C#语言

世界上只有少数几种语言是多功能的&#xff0c;而没有一个像C#那样干净整洁。作者 | Arctek译者 | 谭开朗&#xff0c;责编 | 郭芮出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;以下为译文&#xff1a;最直接的答案是&#xff1a;值得。但我想你不是来找这样的答…

Spring连接mysql数据库错误:Cannot load JDBC driver class '${driver}'

在用Spring使用连接mysql数据库时出现如下错误&#xff1a; Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception isjava.sql.SQLException: Cannot load JDBC driver class ${driver} 错误详细信息如下&…

不一样的 SQL Server 日期格式化

不一样的 SQL Server 日期格式化Intro最近统计一些数据&#xff0c;需要按天/按小时/按分钟来统计&#xff0c;涉及到一些日期的格式化&#xff0c;网上看了一些文章大部分都是使用 CONVERT 来转换的&#xff0c;SQL Server 从 2012 开始增加了 FORMAT 方法&#xff0c;可以使用…

怕被政治烧到,RISC-V基金会决定迁址瑞士

由于政治影响&#xff0c;RISC-V 基金会决定迁址瑞士。FILE PHOTO: Technology on display at Huaweis headquarters in Shenzhen, Guangdong province, China May 29, 2019. REUTERS/Jason Lee去年 12 月份&#xff0c;RISC-V 基金会在一次会议上宣布&#xff0c;它将迁址到一…