【Java集合】LinkedList详解前篇
一、背景
最近在看一本《Redis深度历险》的书籍,书中第二节讲了Redis的5种数据结构,其中看到redis的list结构时,作者提到redis的list跟java的list是有本质区别的,java的list基本数据结构是数组,而redis的list却是linkedlist。然后发现自己对linkedlist这个数据结构了解的并不透彻。所以借此巩固一下。
二、内容
关于LinkedList我会花三篇文章来讲解
- 【前篇】LinkedList的结构分析
- 【中篇】LinkedList的源码分析
- 【后篇】LinkedList与ArrayList的对比
三、前置条件
由于工作中使用的JDK1.8,所以我看的源码,分析的结构都是围绕JDK1.8来分析的
四、正文
1、LinkedList的简单介绍
- LinkedList是有序的双向链表
- LinkedList在内存中开辟的内存不连续【ArrayList开辟的内存是连续的】
- LinkedList插入和删除元素很快,但是查询很慢【相对于ArrayList】
疑问:
- 什么是双向链表?
- 不是连续的内存如何保证的有序性?
- 为什么插入删除元素快?查询却很慢?
2、LinkedList的Node节点结构
如上图,LinkedList是由很多个这样的节点构成
- prev存储的是上一个节点的引用
- item存储的是具体内容
- next存储的是下一个节点的引用
这里解答【1】中的前两个疑问:
- 因为有很多个这种节点,它们依靠存放上、下一个节点的引用,从而形成了有序的链表【类比环环相扣的铁链】
- 由于前后两个节点的引用都保存,所以从前往后、从后往前都能增删改查数据。所以是双向的链表
3、LinkedList的整体结构
如上图,这就是LinkedList的整体结构,可以看到,LinkedList除了很多个node之外,还有first、last这两个变量保存头尾节点的信息
注意:
- 头结点和尾节点并没有关联起来【头节点的prev指向null、尾节点的next指向的也是null】,所以跟循环双向链表区别开来。
这里解答【1】中的最后一个疑问:
- 因为是双向链表结构,所以要删除数据时,直接将【删除节点】的首尾引用指向null,让【删除节点】的【上一个节点】的next引用指向【删除节点】的【下一个节点】,同理,【下一个节点】的prev引用指向【上一个节点】
- 同理,新增数据也一样,【新增节点】的首尾引用分表指向【上一个节点】和【被插入节点】,再将【上一个节点】的next引用指向【新增节点】,【被插入节点】的prev引用指向【新增节点】
- 查询数据慢的原因就在于它不是连续的,所以你没法像ArrayList一样get(index)快速获取数据,它需要在链表上一个个查询,直到找到你要的数据。