Day26 手撕各种集合底层源码(一)

Day26 手撕各种集合底层源码(一)

一、手撕ArrayList底层源码

1、概念: ArrayList的底层实现是基于数组的动态扩容结构。

2、思路:
1.研究继承关系
2.研究属性
3.理解创建集合的过程 – 构造方法的底层原理
4.研究添加元素的过程

3、关键源码:

成员变量

transient Object[] elementData; // 用于存储元素的数组
private int size; // ArrayList中元素的数量

构造方法

public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; // 初始容量为0的空数组
}public ArrayList(int initialCapacity) {if (initialCapacity > 0) {this.elementData = new Object[initialCapacity]; // 指定初始容量的数组} else if (initialCapacity == 0) {this.elementData = EMPTY_ELEMENTDATA; // 初始容量为0的空数组} else {throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);}
}

添加元素方法(add)

public boolean add(E e) {ensureCapacityInternal(size + 1);  // 确保容量足够elementData[size++] = e; // 将元素添加到数组末尾return true;
}private void ensureCapacityInternal(int minCapacity) {if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); // 默认容量为10}ensureExplicitCapacity(minCapacity); // 确保容量足够
}private void ensureExplicitCapacity(int minCapacity) {modCount++;if (minCapacity - elementData.length > 0) {grow(minCapacity); // 扩容}
}private void grow(int minCapacity) {int oldCapacity = elementData.length;int newCapacity = oldCapacity + (oldCapacity >> 1); // 扩容为原来的1.5倍if (newCapacity - minCapacity < 0) {newCapacity = minCapacity;}if (newCapacity - MAX_ARRAY_SIZE > 0) {newCapacity = hugeCapacity(minCapacity);}elementData = Arrays.copyOf(elementData, newCapacity); // 数组扩容
}

4、举例:

public static void main(String[] args) {//ArrayList<String> list = new ArrayList<>();ArrayList<String> list = new ArrayList<>(10000);
​	
​	list.add("aaa");
​	list.add("bbb");
​	list.add("ccc");
​	list.add("ddd");}

二、手撕LinkedList底层源码

1、概念: LinkedList的底层实现是基于双向链表的数据结构。

2、思路:

​ 1.研究继承关系
​ 2.研究属性
​ 3.理解创建集合的过程 – 构造方法的底层原理
​ 4.研究添加元素的过程

3、关键源码:

节点定义

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;}
}

成员变量

transient int size = 0; // LinkedList中元素的数量
transient Node<E> first; // 链表的头节点
transient Node<E> last; // 链表的尾节点

添加元素方法(add)

public boolean add(E e) {linkLast(e); // 将元素添加到链表末尾return true;
}void linkLast(E e) {final Node<E> l = last;final Node<E> newNode = new Node<>(l, e, null); // 创建新节点last = newNode; // 将新节点设置为尾节点if (l == null) {first = newNode; // 如果链表为空,将新节点设置为头节点} else {l.next = newNode; // 将前尾节点的后继节点指向新节点}size++; // 元素数量加1
}

删除元素方法(remove)

public E remove() {return removeFirst(); // 删除链表的第一个节点
}public E removeFirst() {final Node<E> f = first;if (f == null) {throw new NoSuchElementException();}return unlinkFirst(f); // 删除第一个节点
}E unlinkFirst(Node<E> f) {final E element = f.item;final Node<E> next = f.next;f.item = null;f.next = null; // help GCfirst = next; // 将下一个节点设置为头节点if (next == null) {last = null; // 如果下一个节点为空,将尾节点置空} else {next.prev = null; // 将下一个节点的前驱节点置空}size--; // 元素数量减1return element;
}

4、举例:

	public static void main(String[] args) {LinkedList<String> list = new LinkedList<>();list.add("小浩");list.add("小威");list.add("小刘");}

三、手撕Stack底层源码

1、概念: Java中的Stack类是基于动态数组实现的后进先出(LIFO)栈结构。然而,需要注意的是,Java官方推荐使用Deque接口的实现类ArrayDeque来代替Stack类,因为Deque接口提供了更完善的栈操作方法,并且在性能上更优秀。

2、关键源码:

成员变量

private transient Object[] elementData; // 用于存储栈元素的数组
private int elementCount; // 栈中元素的数量

基本方法

public E push(E item) {addElement(item); // 将元素压入栈顶return item;
}public synchronized E pop() {E obj;int len = size();obj = peek(); // 获取栈顶元素removeElementAt(len - 1); // 移除栈顶元素return obj;
}public synchronized E peek() {int len = size();if (len == 0) {throw new EmptyStackException();}return elementAt(len - 1); // 获取栈顶元素
}

扩容方法

java复制代码private void ensureCapacity(int minCapacity) {if (minCapacity - elementData.length > 0) {grow(minCapacity); // 扩容}
}private void grow(int minCapacity) {int oldCapacity = elementData.length;int newCapacity = oldCapacity + (oldCapacity >> 1); // 扩容为原来的1.5倍if (newCapacity - minCapacity < 0) {newCapacity = minCapacity;}if (newCapacity - MAX_ARRAY_SIZE > 0) {newCapacity = hugeCapacity(minCapacity);}elementData = Arrays.copyOf(elementData, newCapacity); // 数组扩容
}

3、举例:

import java.util.Stack;public class Test01 {/*** 知识点:手撕Stack底层源码*/public static void main(String[] args) {Stack<String> stack = new Stack<>();stack.push("aaa");stack.push("bbb");stack.push("ccc");stack.push("ddd");}
}

四、单向链表

1、概念: 单向链表(Singly Linked List)是一种常见的链表数据结构,它由节点组成,每个节点包含数据和指向下一个节点的指针。单向链表的最后一个节点指向空值(null),表示链表的结束。

2、特点:

  1. 单向遍历:只能从头到尾遍历链表,无法反向遍历。
  2. 插入和删除:在已知节点的情况下,可以方便地进行节点的插入和删除操作。
  3. 空间开销:相对于数组,单向链表需要额外的空间来存储指针。

3、应用场景:

  • 需要频繁的插入和删除操作,且不需要反向遍历的场景。
  • 需要在已知节点的情况下进行插入和删除操作的场景。

4、关键源码:

成员变量

private transient Object[] elementData; // 用于存储栈元素的数组
private int elementCount; // 栈中元素的数量

基本方法

public E push(E item) {addElement(item); // 将元素压入栈顶return item;
}
public synchronized E pop() {E obj;int len = size();obj = peek(); // 获取栈顶元素removeElementAt(len - 1); // 移除栈顶元素return obj;
}
public synchronized E peek() {int len = size();if (len == 0) {throw new EmptyStackException();}return elementAt(len - 1); // 获取栈顶元素
}

扩容方法

private void ensureCapacity(int minCapacity) {if (minCapacity - elementData.length > 0) {grow(minCapacity); // 扩容}
}private void grow(int minCapacity) {int oldCapacity = elementData.length;int newCapacity = oldCapacity + (oldCapacity >> 1); // 扩容为原来的1.5倍if (newCapacity - minCapacity < 0) {newCapacity = minCapacity;}if (newCapacity - MAX_ARRAY_SIZE > 0) {newCapacity = hugeCapacity(minCapacity);}elementData = Arrays.copyOf(elementData, newCapacity); // 数组扩容
}

5、举例:

import java.util.Iterator;
public class Test01 {/*** 知识点:实现单向链表*/public static void main(String[] args) {UnidirectionalLinkedList<String> list = new UnidirectionalLinkedList<>();list.add("aaa");list.add("bbb");list.add("ccc");list.add("ddd");list.add("eee");Iterator<String> it = list.iterator();while(it.hasNext()){String element = it.next();System.out.println(element);}}
}
public class UnidirectionalLinkedList<E> {private Node<E> first;private Node<E> last;private int size;public void add(E e){Node<E> node = new Node<>(e, null);if(first == null){first = node;}else{last.next = node;}last = node;size++;}public Iterator<E> iterator(){return new Itr();}public class Itr implements Iterator<E>{private int cursor;private Node<E> node = first;@Overridepublic boolean hasNext() {return cursor != size;}@Overridepublic E next() {E item = node.item;node = node.next;cursor++;return item;}}public static class Node<E>{E item;Node<E> next;public Node(E item, Node<E> next) {this.item = item;this.next = next;}}}

五、双向链表

1、概念: 双向链表(Doubly Linked List)是一种常见的链表数据结构,每个节点包含两个指针,分别指向前一个节点和后一个节点。与单向链表相比,双向链表可以支持双向遍历,提供了更多的灵活性 。

2、特点:

  1. 双向遍历:可以从头到尾或者从尾到头遍历链表,提供了更多的遍历方式。
  2. 插入和删除:在已知节点的情况下,可以更方便地进行节点的插入和删除操作。
  3. 空间开销:相对于单向链表,双向链表需要额外的空间来存储前驱节点的指针。

3、应用场景:

  • 需要频繁的插入和删除操作,且需要双向遍历的场景。
  • 需要在已知节点的情况下进行插入和删除操作的场景。

4、基本操作:

  1. 插入节点:在给定节点后或前插入新节点,需要更新前后节点的指针。
  2. 删除节点:删除给定节点,同样需要更新前后节点的指针。
  3. 遍历:可以从头到尾或者从尾到头遍历链表,获取节点的值或执行其他操作。

5、代码理解:

import java.util.Iterator;
import com.qf.bidirectional_linked_list.BidirectionalLinkedList.Node;public class Test01 {/*** 知识点:实现双向链表*/public static void main(String[] args) {BidirectionalLinkedList<String> list = new BidirectionalLinkedList<>();list.add("aaa");list.add("bbb");list.add("ccc");list.add("ddd");list.add("eee");//正序遍历Iterator<String> it = list.iterator();while(it.hasNext()){String element = it.next();System.out.println(element);}System.out.println("-----------------------");//倒序遍历Node<String> node = list.getLast();while(node != null){System.out.println(node.item);node = node.prev;}}
}public class BidirectionalLinkedList<E> {private Node<E> first;private Node<E> last;private int size;public void add(E e){Node<E> l = last;Node<E> node = new Node<>(l,e, null);if(first == null){first = node;}else{last.next = node;}last = node;size++;}public Node<E> getLast() {return last;}public Iterator<E> iterator(){return new Itr();}public class Itr implements Iterator<E>{private int cursor;private Node<E> node = first;@Overridepublic boolean hasNext() {return cursor != size;}@Overridepublic E next() {E item = node.item;node = node.next;cursor++;return item;}}public static class Node<E>{Node<E> prev;E item;Node<E> next;public Node(Node<E> prev,E item, Node<E> next) {this.prev = prev;this.item = item;this.next = next;}}}

LinkedList理解图
在这里插入图片描述

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

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

相关文章

vue实现把Ox格式颜色值转换成rgb渐变颜色值(开箱即用)

图示&#xff1a; 核心代码&#xff1a; //将0x格式的颜色转换为Hex格式&#xff0c;并计算插值返回rgb颜色 Vue.prototype.$convertToHex function (colorCode1, colorCode2, amount) {// 确保输入是字符串&#xff0c;并检查是否以0x开头let newCode1 let newCode2 if (t…

关系型数据库mysql(5)存储引擎

目录 一.存储引擎的概念 二. MyISAM 和 InnoDB 2.1MyISAM介绍 2.2MyISAM支持的存储格式 2.2.1静态表&#xff08;固定长度表&#xff09; 2.2.2动态表 2.2.3压缩表 2.3场景举例 2.4.InnoDB 2.4.1场景举例 2.4.2企业选择存储引擎依据 三.查看存储引擎 3.1查看当前数…

C++中的STL简介与string类

目录 STL简介 STL的版本 STL的六大组件 string类 标准库中的string类 string类的常用接口 string类对象对容量的操作 size()函数与length()函数 capacity()函数 capacity的扩容方式 reserve()函数 resize()函数 string类对象的操作 push_back()函数 append()函数 operator()函数…

【01-20】计算机网络基础知识(非常详细)从零基础入门到精通,看完这一篇就够了

【01-20】计算机网络基础知识&#xff08;非常详细&#xff09;从零基础入门到精通&#xff0c;看完这一篇就够了 以下是本文参考的资料 欢迎大家查收原版 本版本仅作个人笔记使用1、OSI 的七层模型分别是&#xff1f;各自的功能是什么&#xff1f;2、说一下一次完整的HTTP请求…

记录何凯明在MIT的第一堂课:神经网络发展史

https://www.youtube.com/watch?vZ5qJ9IxSuKo 目录 表征学习 主要特点&#xff1a; 方法和技术&#xff1a; LeNet 全连接层​ 主要特点&#xff1a; 主要特点&#xff1a; 网络结构&#xff1a; AlexNet 主要特点&#xff1a; 网络结构&#xff1a; Sigmoid Re…

经典永不过时 Wordpress模板主题

经得住时间考验的模板&#xff0c;才是经典模板&#xff0c;带得来客户的网站&#xff0c;才叫NB网站。 https://www.jianzhanpress.com/?p2484

第十五届蓝桥杯第三期模拟赛第十题 ← 上楼梯

【问题描述】 小蓝要上一个楼梯&#xff0c;楼梯共有 n 级台阶&#xff08;即小蓝总共要走 n 级&#xff09;。小蓝每一步可以走 a 级、b 级或 c 级台阶。 请问小蓝总共有多少种方案能正好走到楼梯顶端&#xff1f;【输入格式】 输入的第一行包含一个整数 n 。 第二行包含三个整…

vulfocus环境搭建(kali搭建)

Vulfocus 是一个漏洞集成平台&#xff0c;将漏洞环境 docker 镜像&#xff0c;放入即可使用&#xff0c;开箱即用。 安装docker环境 个人不建议随意更换apt源&#xff0c;我换了几次遇到很多问题。 apt-get update apt-get upgrade&#xff08;时间很久&#xff09; apt-get i…

基于springboot的人事管理系统

人事管理系统 摘 要 人事管理系统理工作是一种繁琐的&#xff0c;务求准确迅速的信息检索工作。随着计算机信息技术的飞速发展&#xff0c;人类进入信息时代&#xff0c;社会的竞争越来越激烈&#xff0c;人事就越显示出其不可或缺性&#xff0c;成为学校一个非常重要的模块。…

防止恶意软件和网络攻击的简单贴士

如今&#xff0c;缺少互联网的生活是难以想象的。然而&#xff0c;互联网的匿名性导致了网络攻击和恶意软件很猖獗。恶意软件会损坏我们的设备、窃取个人数据&#xff0c;并导致金钱损失。因此&#xff0c;保护计算机免受这些威胁显得至关重要。 一、确保操作系统和软件是最新版…

企业数据资产管理的战略价值与实施策略

一、引言 数据资产不仅记录了企业的历史运营情况&#xff0c;更能够揭示市场的未来趋势&#xff0c;为企业的决策提供有力支持。因此&#xff0c;如何有效地管理和利用数据资产&#xff0c;已经成为企业竞争力的重要体现。本文将探讨企业数据资产管理的战略价值与实施策略&…

URL编码:原理、应用与安全性

title: URL编码&#xff1a;原理、应用与安全性 date: 2024/3/29 18:32:42 updated: 2024/3/29 18:32:42 tags: URL编码百分号编码特殊字符处理网络安全应用场景标准演变未来发展 在网络世界中&#xff0c;URL&#xff08;统一资源定位符&#xff09;是我们访问网页、发送请求…

设计模式之单例模式精讲

UML图&#xff1a; 静态私有变量&#xff08;即常量&#xff09;保存单例对象&#xff0c;防止使用过程中重新赋值&#xff0c;破坏单例。私有化构造方法&#xff0c;防止外部创建新的对象&#xff0c;破坏单例。静态公共getInstance方法&#xff0c;作为唯一获取单例对象的入口…

速通汇编(二)汇编mov、addsub指令

一&#xff0c;mov指令 mov指令的全称是move&#xff0c;从字面上去理解&#xff0c;作用是移动&#xff08;比较确切的说是复制&#xff09;数据&#xff0c;mov指令可以有以下几种形式 无论哪种形式&#xff0c;都是把右边的值移动到左边 mov 寄存器&#xff0c;数据&#…

AI 创新领跑者,KIP Protocol 如何理解 Decentralized AI

随着 OpenAI 的 Sora 推动 AI 赛道的热度攀升&#xff0c;AI 领域再次成为科技和投资界的焦点。KIP Protocol 是面向 AI 模型制作者、App 开发者和数据所有者构建的去中心化 Web3 协议层&#xff0c;使数据可在 Web3 中安全地进行交易和货币化。KIP Protocol 由 Animoca Ventur…

Jenkins实现CICD

Jenkins实现CICD JenkinsCI简介环境安装新建任务源码管理构建配置发送邮件配置自动化项目定时构建 JenkinsCD简介配置ssh保证其可以免登录接下来配置github的webhook正式实现自动化打包master主分支的代码将前端三剑客代码文件发送到网站服务器对应的tomcat Jenkins面试题 Jenk…

个人简历主页搭建系列-04:网站初搭建

准备工作差不多了&#xff0c;该开始搭建网站了&#xff01; 这次我们先把网站搭建部署起来&#xff0c;关于后续主题内容等更换留到后续。 创建源码文件夹 首先通过 hexo 创建本地源码文件夹。因为最终部署的 github 仓库格式为 websiteName.github.io&#xff08;websiteN…

Gartner发布新兴技术指南:生成式人工智能和深度伪造对身份验证的影响

使用生成式人工智能(GenAI)技术生成的 Deepfakes&#xff08;深度伪造&#xff09; 对身份验证的完整性构成了根本威胁。身份验证产品领导者必须了解这一新兴威胁&#xff0c;并采取积极主动的方法来区分和保护其解决方案产品。 主要发现 活体检测技术对于防御深度伪造以及在身…

【每日力扣】332. 重新安排行程与51. N 皇后

&#x1f525; 个人主页: 黑洞晓威 &#x1f600;你不必等到非常厉害&#xff0c;才敢开始&#xff0c;你需要开始&#xff0c;才会变的非常厉害。 332. 重新安排行程 给你一份航线列表 tickets &#xff0c;其中 tickets[i] [fromi, toi] 表示飞机出发和降落的机场地点。请你…

代码随想录算法训练营 DAY 24 | 回溯理论基础 77.组合 + 剪枝优化

回溯理论 回溯法就是递归函数&#xff0c;纯暴力搜索 解决的问题 组合&#xff08;无顺序&#xff09; 1 2 3 4 给出大小为2的所有组合 切割字符串 子集问题 1 2 3 4&#xff0c;子集有1 2 3 4,12,13,14&#xff0c;…123 124… 排列&#xff08;有顺序&#xff09; 棋盘…