集合底层数据结构简单实现
一、LinkedList集合
LinkedList简介:
LinkedList 是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。
LinkedList 实现 List 接口,能对它进行队列操作。
LinkedList 实现 Deque 接口,即能将LinkedList当作双端队列使用。
LinkedList 实现了Cloneable接口,即覆盖了函数clone(),能克隆。
LinkedList 实现java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。
LinkedList 是非同步的。
LinkedList底层源码:
LinkedList实际上是通过双向链表去实现的。既然是双向链表,那么它的顺序访问会非常高效,而随机访问效率比较低。
既然LinkedList是通过双向链表的,但是它也实现了List接口{也就是说,它实现了get(int location)、remove(int location)等“根据索引值来获取、删除节点的函数”}。LinkedList是如何实现List的这些接口的,如何将“双向链表和索引值联系起来的”?
实际原理非常简单,它就是通过一个计数索引值来实现的。例如,当我们调用get(int location)时,首先会比较“location”和“双向链表长度的1/2”;若前者大,则从链表头开始往后查找,直到location位置;否则,从链表末尾开始先前查找,直到location位置。
这就是“双线链表和索引值联系起来”的方法。
代码模拟双向链表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | class Demo11 { public static void main(String[] args) { /** * 1.创建数据 */ Node node1 = new Node( "李云峰" ); Node node2 = new Node( "刘文闯" ); Node node3 = new Node( "刘承毅" ); /** * 2.将节点连接 */ node1.next = node2; node2.next = node3; node3.pre = node2; node2.pre = node1; /** * 3.设置双向链表的头尾节点 */ Node first = node1; Node last = node3; /** * 4.遍历双向链表 */ while (first != null ) { System. out .println(first); // 指向下一节点 first = first.next; } } } class Node { /** * 姓名 */ Object message; /** * 指向前一个节点 */ Node pre; /** * 指向后一个节点 */ Node next; public Node(Object message) { this .message = message; } @Override public String toString() { return (String) message; } } |
遍历结果:
1 2 3 | 李云峰 刘文闯 刘承毅 |
插入一个Node节点:
1 public static void main(String[] args) { 2 /** 3 * 1.创建数据 4 */ 5 Node node1 = new Node("李云峰"); 6 Node node2 = new Node("刘文闯"); 7 Node node3 = new Node("刘承毅"); 8 /** 9 * 2.将节点连接 10 */ 11 node1.next = node2; 12 node2.next = node3; 13 node3.pre = node2; 14 node2.pre = node1; 15 /** 16 * 3.设置双向链表的头尾节点 17 */ 18 Node first = node1; 19 Node last = node3; 20 // 添加一个节点 21 Node node4 = new Node("张志喜"); 22 node3.pre = node4; 23 node2.next = node4; 24 node4.next = node3; 25 node4.pre = node2; 26 /** 27 * 4.遍历双向链表 28 */ 29 while (first != null) { 30 System.out.println(first); 31 // 指向下一节点 32 first = first.next; 33 } 34 }
遍历输出:
1 2 3 4 | 李云峰 刘文闯 张志喜 刘承毅 |
二、HashSet
HashSet这个类实现了Set集合,实际为一个HashMap的实例。对集合的迭代次序没有任何保证; 特别是,它不能保证订单会随着时间的推移保持不变。这个类允许null 元素(只允许有一个)
底层的存储结构(数组+链表+红黑树)
注意:同时满足(链表元素达到8个,Table长度大于64,会自动转换为红黑树数据数据结构进行存储)
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | /** * @author zhangzhixi * @date 2021-6-19 12:47 */ public class HashSet底层实现 { public static void main(String[] args) { // 1、创建一个数组,数组类型是Node Node[] table = new Node[10]; // 2、创建节点 Node node1 = new Node( "刘文闯" , null ); // 3、将节点放到数组下标为2的table中去 table[2] = node1; // 4、继续放入节点 Node node2 = new Node( "李云峰" , null ); // 4.1、将node2挂载到node1 node1.next = node2; System. out .println(table[0]); } } class Node { String name; Node next; public Node(String name, Node next) { this .name = name; this .next = next; } @Override public String toString() { return "Node{" + "name='" + name + '\ '' + ", next=" + next + '}' ; } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话