数据结构之ArrayList
系列文章目录
目录
系列文章目录
前言
一、数据结构的前置语法
1. 时空复杂度
2. 包装类
3. 泛型
二、ArrayList 和顺序表
1. 顺序表的模拟实现
2. 源码
3. ArrayList 的优缺点
前言
本文介绍数据结构的前置算法,以及 ArrayList 的模拟实现,部分源码及优缺点概括。
一、数据结构的前置语法
1. 时空复杂度
时间复杂度和空间复杂度:用来衡量算法的效率(时间和空间),通常用大O渐进法进行表示;
常见的时间复杂度:O(1), O(logN), O(N), O(N*logN), O(N^2);
2. 包装类
解释下面代码的原理:
Integer a = 100;
Integer b = 100;System.out.println(a == b); // 输出 trueInteger c = 200;
Integer d = 200;System.out.println(c == d); // 输出 false
valueOf(): Integer 源码:
public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);
}
Integer.Cache.high = 127, Integer.Cache.low = -128
cache数组中在 [0, 255] 空间中存的是 -128 ~127;
如果数字 i 的值在 [-128, 127] 之间,返回 cache 数组的对应下标 [0, 255] 区间的值,即 -128 ~ 127;否则则会 new 一个新的引用变量;
因此当 i 在 [-128, 127] 之间,返回的都是同一个哈希值,即引用变量相等,否则返回不同的哈希值,即引用变量不相等;
3. 泛型
类名后面写一个 "<T>" ,表示这是一个泛型类;
"<>" 只能存放包装类型,不能存放基本类型;
编译的时候会把 T 类型都替换成 Object 类型,这称为泛型的擦除机制;
泛型的上界:
泛型类:class 类名<T extends XXX> ,XXX 就是泛型的上界;
泛型方法 :<T> 返回类型 方法名<T extends XXX>(){...}, XXX 就是泛型的上界;
二、ArrayList 和顺序表
顺序表底层是一个数组,是使用数组来完成的一种结构;
实现了 List 接口,通常使用 "List<T> list = new ArrayList<>() " 这种向上转型的形式去定义顺序表;
1. 顺序表的模拟实现
下面模拟实现顺序表,理解顺序表的底层原理:
定义一个数组 elem,用于存放元素,定义一个 usedSize 用于表示存放了几个元素;
定义一个常数 DEFAULT_SIZE,用来表示新建一个顺序表默认开辟空间的大小;
定义一个无参的构造方法,默认开辟的空间大小为 DEFAULT_SIZE;
定义一个有一个参数的构造方法,参数用于指定开辟空间的大小;
public class MyArrayList {private int[] elem;private int usedSize;private static final int DEFAULT_SIZE = 10;public MyArrayList(){this.elem = new int[DEFAULT_SIZE];}public MyArrayList(int capacity){this.elem = new int[capacity];}// 方法的位置// ......
}
下面实现顺序表的方法(增删改查):
打印顺序表的所有元素:
// 打印元素public void display(){for(int i = 0; i < usedSize; i++){System.out.print(this.elem[i] + " ");}}
向顺序表中增加一个元素:
注意:在顺序表中增加元素的时候,需要先判断当前是否已经存满,如果存满了要先进行扩容才可以再往顺序表中添加元素;
isFull(): boolean 判断顺序表是否存满;每次增加元素都需要判断顺序表是否存满;
add(int data): void 向顺序表最后一个位置新增一个元素;
add(int pos, int data): void 向顺序表的 pos 位置新增一个元素;
需要判断 pos 位置是否合法,不合法要抛出异常;
如果合法,就要将 pos 位置以及 pos 后面的元素,往后挪一个位置,考虑到可能覆盖后一个元素的问题,需要从后往前依次向后挪每个元素;
增加元素一定不要忘记 usedSize++;
// 判断是否满public boolean isFull(){if(this.usedSize == this.elem.length) {return true;}return false;}// 新增元素,默认在数组最后新增public void add(int data){if(isFull()){// 扩容this.elem = Arrays.copyOf(this.elem, 2 * this.elem.length);}this.elem[usedSize] = data;usedSize++;}// 在 pos 位置新增元素public void add(int pos, int data){if(pos < 0 || pos > this.usedSize){throw new PosOutOfBoundsException(pos + "位置不合法");}if(isFull()){// 扩容this.elem = Arrays.copyOf(this.elem, 2 * this.elem.length);}for(int i = usedSize - 1; i >= pos; i--){this.elem[i + 1] = this.elem[i];}this.elem[pos] = data;this.usedSize++;}
查找元素:
contains(int toFind): boolean 判断元素 toFind 是否在顺表中存在;
indexOf(int toFind): int 找元素 toFind 的下标,找到则返回对应下标,找不到返回 -1;
checkPos(int pos): void 判断下标是否合法,查找某个下标元素需要先判断下标是否合法,不合法直接抛出异常;
get(int pos): int 获取 pos 位置元素的下标;需要先判断给定的 pos 下标是否合法;
// 判断是否包含某个元素public boolean contains(int toFind){for(int i = 0; i < this.usedSize; i++){// 如果是引用类型,可以使用 equals 方法if(this.elem[i] == toFind){return true;}}return false;}// 查找某个元素对应的位置public int indexOf(int toFind){for(int i = 0; i < this.usedSize; i++){if(this.elem[i] == toFind){return i;}}return -1;}// 判断下标是否合法 private void checkPos(int pos){if(pos < 0 || pos >= this.usedSize){throw new PosOutOfBoundsException(pos + "位置不合法");}}// 获取某个位置的元素public int get(int pos){checkPos(pos);return this.elem[pos];}
修改某个位置元素:
set(int pos, int value): void 修改 pos 位置的元素为 value,修改前同样需要判断 pos 位置是否合法;
// 给 pos 位置的元素设为 valuepublic void set(int pos, int value){checkPos(pos);this.elem[pos] = value;}
删除某个元素:
remove(int toRemove): void 删除元素 toRemove;
先查找该元素的下标;
如果元素不存在直接返回;
如果元素存在则删除该元素,并将该元素后面的元素都往前移一个位置;如果是引用类型的数据,一定记得把最后一个引用置 null;
删除元素一定不能忘记 usedSize--;
// 删除第一次出现的关键字 keypublic void remove(int toRemove){int index = indexOf(toRemove);if(index == -1){return;}for(int i = index; i < this.usedSize - 1; i++){this.elem[i] = this.elem[i + 1];}// 如果是引用类型,最后一个位置就要置 null// this.elem[this.usedSize - 1] = nullthis.usedSize--;}
求顺序表长度:
size(): int 求顺序表长度,直接返回 usedSize 即可;
// 获取顺序表长度public int size(){return this.usedSize;}
清空顺序表:
clear(): void 清空顺序表;
如果是基本类型,直接将 usedSize 置 0 即可;
如果是引用类型,需要遍历一遍顺序表,将每个引用都置 null;
// 清空顺序表public void clear(){// 如果是引用类型,就要遍历置为 null
// for(int i = 0; i < this.usedSize; i++){
// this.elem[i] = null;
// }this.usedSize = 0;}
2. 源码
构造方法:
ArrayList(int initialCapacity):一个参数的构造方法,initialCapacity 用于指定顺序表的空间;
ArrayList():无参的构造方法,并没有分配内存,第一次增加元素的时候才会扩容;
ArrayList(Collection<? extends E> c):可以传 E 类型的子类或者 E 类型本身的 实现了Collection 接口的数据结构;除了 Map 没实现, Collection,List,Queue,Set 都实现了;
public ArrayList(int initialCapacity) {if (initialCapacity > 0) {this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {this.elementData = EMPTY_ELEMENTDATA;} else {throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}}/*** Constructs an empty list with an initial capacity of ten.*/public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}/*** Constructs a list containing the elements of the specified* collection, in the order they are returned by the collection's* iterator.** @param c the collection whose elements are to be placed into this list* @throws NullPointerException if the specified collection is null*/public ArrayList(Collection<? extends E> c) {elementData = c.toArray();if ((size = elementData.length) != 0) {// c.toArray might (incorrectly) not return Object[] (see 6260652)if (elementData.getClass() != Object[].class)elementData = Arrays.copyOf(elementData, size, Object[].class);} else {// replace with empty array.this.elementData = EMPTY_ELEMENTDATA;}}
ArrayList 扩容机制:
Object[] elementData; // 存放元素的空间private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // 默认空间private static final int DEFAULT_CAPACITY = 10; // 默认容量大小public boolean add(E e) {ensureCapacityInternal(size + 1); // Increments modCount!!elementData[size++] = e;return true;}private void ensureCapacityInternal(int minCapacity) {ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));}private static int calculateCapacity(Object[] elementData, int minCapacity) {if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {return Math.max(DEFAULT_CAPACITY, minCapacity);}return minCapacity;}private void ensureExplicitCapacity(int minCapacity) {modCount++;// overflow-conscious codeif (minCapacity - elementData.length > 0)grow(minCapacity);}private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;private void grow(int minCapacity) {// 获取旧空间大小int oldCapacity = elementData.length;// 预计按照1.5倍方式扩容int newCapacity = oldCapacity + (oldCapacity >> 1);// 如果用户需要扩容大小 超过 原空间1.5倍,按照用户所需大小扩容if (newCapacity - minCapacity < 0)newCapacity = minCapacity;// 如果需要扩容大小超过MAX_ARRAY_SIZE,重新计算容量大小if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);// 调用copyOf扩容elementData = Arrays.copyOf(elementData, newCapacity);}private static int hugeCapacity(int minCapacity) {// 如果minCapacity小于0,抛出OutOfMemoryError异常if (minCapacity < 0)throw new OutOfMemoryError();return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;}
3. ArrayList 的优缺点
优点:可以通过下标进行随机访问,时间复杂度 O(1);
缺点:
往某个位置添加元素,需要往后移动后面的元素;
删除某个元素,需要移动把后面的元素往前移动;
扩容的时候,每次都需要拷贝所有元素;扩容之后可能会浪费空间;
总结:适合静态的数据查找和更新,不适合插入和删除数据。
相关文章:
数据结构之ArrayList
系列文章目录 目录 系列文章目录 前言 一、数据结构的前置语法 1. 时空复杂度 2. 包装类 3. 泛型 二、ArrayList 和顺序表 1. 顺序表的模拟实现 2. 源码 3. ArrayList 的优缺点 前言 本文介绍数据结构的前置算法,以及 ArrayList 的模拟实现,部…...

DDR4读写压力测试
1.1测试环境 1.1.1整体环境介绍 板卡: pcie-403板卡 主控芯片: Xilinx xcvu13p-fhgb2104-2 调试软件: Vivado 2018.3 代码环境: Vscode utf-8 测试工程: pcie403_user_top 1.1.2硬件介绍 UD PCIe-403…...
uniapp 开发企业微信小程序时,如何在当前页面真正销毁前或者关闭小程序前调用一个api接口
在 UniApp 开发企业微信小程序时,若需在页面销毁或小程序关闭前调用 API 接口,需结合页面生命周期和应用生命周期实现。以下是具体实现方案及注意事项: 一、在页面销毁前调用 API(页面级) 通过页面生命周期钩子 onUnl…...
WPF 按钮点击音效实现
WPF 按钮点击音效实现 下面我将为您提供一个完整的 WPF 按钮点击音效实现方案,包含多种实现方式和高级功能: 完整实现方案 MainWindow.xaml <Window x:Class"ButtonClickSound.MainWindow"xmlns"http://schemas.microsoft.com/win…...

编写测试用例
测试用例(Test Case)是用于测试系统的要素集合 目录 编写测试用例作用 编写测试用例要包含七大元素 测试用例的设计方法 1、等价类法 2、边界值法 3、正交表法 4、判定表法 5、错误推测法 6、场景法 编写测试用例作用 1、确保功能全面覆盖…...
解释程序(Python)不需要生成机器码 逐行解析 逐行执行
在计算机组成原理中,解释程序(Interpreter)通常不会生成独立的机器码,但具体情况取决于解释器的实现方式。以下是详细分析: 1. 传统解释程序:不生成机器码 直接逐行执行: 经典的解释器ÿ…...

每日Prompt:隐形人
提示词 黑色棒球帽,白色抹胸、粉色低腰短裙、白色襪子,黑色鞋子,粉紅色背包,衣服悬浮在空中呈现动态姿势,虚幻引擎渲染风格,高清晰游戏CG质感,户外山林背景,画面聚焦在漂浮的衣服上…...

TensorFlow深度学习实战(19)——受限玻尔兹曼机
TensorFlow深度学习实战(19)——受限玻尔兹曼机 0. 前言1. 受限玻尔兹曼机1.1 受限玻尔兹曼机架构1.2 受限玻尔兹曼机的数学原理 2. 使用受限玻尔兹曼机重建图像3. 深度信念网络小结系列链接 0. 前言 受限玻尔兹曼机 (Restricted Boltzmann Machine, RB…...

告别手动绘图!基于AI的Smart Mermaid自动可视化图表工具搭建与使用指南
以下是对Smart Mermaid的简单介绍: 一款基于 AI 技术的 Web 应用程序,可将文本内容智能转换为 Mermaid 格式的代码,并将其渲染成可视化图表可以智能制作流程图、序列图、甘特图、状态图等等,并且支持在线调整、图片导出可以Docke…...

【Oracle】安装单实例
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 安装前的准备工作1.1 硬件和系统要求1.2 检查系统环境1.3 下载Oracle软件 2. 系统配置2.1 创建Oracle用户和组2.2 配置内核参数2.3 配置用户资源限制2.4 安装必要的软件包 3. 目录结构和环境变量3.1 创建Ora…...
C++测开,自动化测试,业务(第一段实习)
目录 🌼前言 一,实习经历怎么写简历 🌹业务理解 🎂结构化表达 二,实习 🦂技术和流程卡点 🔑实习收获 / 代码风格 三,测试理论,用例设计,工具链 &…...

QT中更新或添加组件时出现“”qt操作至少需要一个处于启用状态的有效资料档案库“解决方法”
在MaintenanceTool.exe中点击下一步 第一个: 第二个: 第三个: 以上任意一个放入资料库中...

论文速读《UAV-Flow Colosseo: 自然语言控制无人机系统》
论文链接:https://arxiv.org/abs/2505.15725项目主页:https://prince687028.github.io/UAV-Flow/ 0. 简介 近年来,无人机技术蓬勃发展,但如何让无人机像智能助手一样理解并执行人类语言指令,仍是一个前沿挑战。现有研…...

ES6+中Promise 中错误捕捉详解——链式调用catch()或者async/await+try/catch
通过 unhandledrejection 捕捉未处理的 Promise 异常,手动将其抛出,最终让 window.onerror 捕捉,从而统一所有异常的处理逻辑 规范代码:catch(onRejected)、async...awaittry...catch 在 JavaScript 的 Pro…...
CDN安全加速:HTTPS加密最佳配置方案
CDN安全加速的HTTPS加密最佳配置方案需从证书管理、协议优化、安全策略到性能调优进行全链路设计,以下是核心实施步骤与注意事项: 一、证书配置与管理 证书选择与格式 证书类型:优先使用受信任CA机构颁发的DV/OV/EV证…...

解常微分方程组
Euler法 function euler_method % 参数设置 v_missile 450; % 导弹速度 km/h v_enemy 90; % 敌艇速度 km/h % 初始条件 x0 0; % 导弹初始位置 x y0 0; % 导弹初始位置 y xe0 120; % 敌艇初始位置 y t0 0; % 初始时间 % 时间步长和总时间 dt 0.01; % 时间步长 t_final …...

C++实现汉诺塔游戏自动完成
目录 一、汉诺塔的规则二、数学递归推导式三、步骤实现(一)汉诺塔模型(二)递归实现(三)显示1.命令行显示2.SDL图形显示 四、处理用户输入及SDL环境配置五、总结六、源码下载 一、汉诺塔的规则 游戏由3根柱子和若干大小不一的圆盘组成,初始状态下,所有的…...
在 ABP VNext 中集成 Serilog:打造可观测、结构化日志系统
🚀 在 ABP VNext 中集成 Serilog:打造可观测、结构化日志系统 📚 目录 🚀 在 ABP VNext 中集成 Serilog:打造可观测、结构化日志系统1. 为什么要使用结构化日志? 🤔2. 核心集成步骤 Ὦ…...

pikachu靶场通关笔记07 XSS关卡03-存储型XSS
目录 一、XSS 二、存储型XSS 三、源码分析 四、渗透实战 1、输入mooyuan试一试 2、注入Payload 3、查看数据库 4、再次进入留言板页面 本系列为通过《pikachu靶场通关笔记》的XSS关卡(共10关)渗透集合,通过对XSS关卡源码的代码审计找到XSS风险的…...
GitLab CI、GitHub Actions和Jenkins进行比较
特性/工具JenkinsGitLab CIGitHub Actions架构设计哲学Master/Agent分布式架构,通过插件扩展功能代码与CI/CD强耦合,内置Git仓库,基于Runner注册机制事件驱动,与GitHub深度集成,基于虚拟机的Job执行单元核心运行机制支…...
strcat及其模拟实现
#define _CRT_SECURE_NO_WARNINGS strcat 追加字符串 str "string"(字符串) cat "concatenate"(连接 / 追加) char* strcat(char* destination, const char* source); strcat的应用 方法一ÿ…...

OpenCV CUDA模块直方图计算------用于在 GPU 上执行对比度受限的自适应直方图均衡类cv::cuda::CLAHE
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 cv::cuda::CLAHE 是 OpenCV 的 CUDA 模块中提供的一个类,用于在 GPU 上执行对比度受限的自适应直方图均衡(Contrast Limi…...

华为OD机试真题——矩形绘制(2025A卷:200分)Java/python/JavaScript/C/C++/GO最佳实现
2025 A卷 200分 题型 本专栏内全部题目均提供Java、python、JavaScript、C、C++、GO六种语言的最佳实现方式; 并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析; 本文收录于专栏:《2025华为OD真题目录+全流程解析+备考攻略+经验分…...
通义开源视觉感知多模态 RAG 推理框架 VRAG-RL:开启多模态推理新时代
通义实验室的自然语言智能团队,凭借深厚的技术积累与创新精神,成功研发并开源了视觉感知多模态 RAG 推理框架 VRAG-RL,为 AI 在复杂视觉信息处理领域带来了重大突破。 传统 RAG 方法的局限 传统的检索增强型生成(RAG࿰…...
爬虫入门:从基础到实战全攻略
🧠 一、爬虫基础概念 1.1 爬虫定义 爬虫(Web Crawler)是模拟浏览器行为,自动向服务器发送请求并获取响应数据的一种程序。主要用于从网页中提取结构化数据,供后续分析、展示或存储使用。 1.2 爬虫特点 数据碎片化&…...
qemu安装risc-V 64
参考这篇文章https://developer.aliyun.com/article/1323996,其中在wsl下面安装可能会报错环境变量中有空格。 # clean_path.sh#!/bin/bash# 备份旧 PATH OLD_PATH"$PATH"# 过滤掉包含空格、制表符、换行的路径 CLEAN_PATH"" IFS: read -ra PA…...

JDBC连不上mysql:Unable to load authentication plugin ‘caching_sha2_password‘.
最近为一个spring-boot项目下了mysql-9.3.0,结果因为mysql版本太新一直报错连不上。 错误如下: 2025-06-01 16:19:43.516 ERROR 22088 --- [http-nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispat…...
AsyncIOScheduler与BackgroundScheduler的线程模型对比
1. BackgroundScheduler的线程机制 多线程模型:BackgroundScheduler基于线程池执行任务,默认通过ThreadPoolExecutor创建独立线程处理任务,每个任务运行在单独的线程中,主线程不会被阻塞。适用场景:适合同步…...
Python+MongoDb使用手册(精简)
这里是学了下面链接的内容,加上一些自己学习的内容综合的,大家也可以去看看这篇文章,写的特别好 【python】在Python中操作MongoDB的详细用法教程与实战案例分享_python轻松入门,基础语法到高阶实战教学-CSDN专栏 1 库࿱…...
前端面经 协商缓存和强缓存
HHTTPTTP缓存 协商缓存和强缓存 核心区别是否向服务器发起请求验证资源过期 强缓存 浏览器直接读取本地缓存,不发请求 HTTP响应头 Cache-Control:max-age3600资源有效期 Expires优先级低 如果有效浏览器返回200(浏览器换伪造的200) 应用静态资源 协商缓存 OK如果 1强缓…...