数据结构之ArrayList与顺序表(上)
找往期文章包括但不限于本期文章中不懂的知识点:
个人主页:我要学编程(ಥ_ಥ)-CSDN博客
所属专栏:数据结构(Java版)
顺序表的学习,点我
上面这篇博文是关于顺序表的基础知识,以及顺序表的实现。
目录
手动实现顺序表的源码:
分析Java 8 的 ArrayList 的源码
字段:
构造方法:
ArrayList本身的扩容机制和分配内存机制
ArrayList常见操作
ArrayList的遍历
普通for循环遍历
for-each遍历
toString方法遍历
迭代器遍历
手动实现顺序表的源码:
下面是Java版的顺序表源码:
public class MyArraylist {public int[] elem;public int usedSize;//0//默认容量private static final int DEFAULT_SIZE = 10;public MyArraylist() {this.elem = new int[DEFAULT_SIZE];}/*** 打印顺序表:*   根据usedSize判断即可*/public void display() {for (int i = 0; i < this.usedSize; i++) {System.out.print(this.elem[i]+" ");}System.out.println();}// 新增元素,默认在数组最后新增public void add(int data) {// 增加元素之前得先判断数组是否已满if (isFull()) {expansion();}// 尾插数据不需要判断 pos 位置是否合法elem[this.usedSize++] = data;}// 扩容private void expansion() {// 原来数组的2倍扩容this.elem = Arrays.copyOf(this.elem, 2 * this.elem.length);}/*** 判断当前的顺序表是不是满的!* @return true:满   false代表空*/public boolean isFull() {// 判断这个数组的有效元素个数是否等于数组的长度return this.usedSize == this.elem.length;}private boolean checkPosInAdd(int pos) {if (pos < 0 || pos > this.usedSize) {return false;}return true;//合法}// 在 pos 位置新增元素public void add(int pos, int data) throws PosofAddException{if (!checkPosInAdd(pos)) {throw new PosofAddException("add(int pos, int data) " +"pos位置不合法");}// 判断是否为尾插if (pos == this.usedSize) {add(data);}else {// 开始移除元素(从后往前移除)for (int i = this.usedSize; i > pos; i--) {this.elem[i] = this.elem[i-1];}// 开始插入数据this.elem[pos] = data;this.usedSize++;}}// 判定是否包含某个元素public boolean contains(int toFind) {// 先判断这个数组是否有元素if (isEmpty()) {return false;}for (int i = 0; i < this.usedSize; i++) {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;}// 获取 pos 位置的元素public int get(int pos) throws PosofGetException{if (pos < 0 || pos > this.usedSize) {throw new PosofGetException("get(int pos)" +"pos位置不合法");}return this.elem[pos];}private boolean isEmpty() {// 有效数据个数为0,就是为空return this.usedSize == 0;}// 给 pos 位置的元素设为【更新为】 valuepublic void set(int pos, int value) throws PosofSetException{// 先得判断这个 pos 位置是否合法if (pos < 0 || pos >= this.usedSize) {throw new PosofSetException("set(int pos, int value)" +"要修改的位置不合法");}this.elem[pos] = value;}/*** 删除第一次出现的关键字key* @param key*/public void remove(int key) throws PosofRemoveException{int pos = indexOf(key); // 下标if (pos < 0) {throw new PosofRemoveException("remove(int key)" +"没有您要删除的数据");}for (int i = pos; i < this.usedSize - 1; i++) {// 后一个位置往前覆盖this.elem[i] = this.elem[i+1];}this.usedSize--;}// 获取顺序表长度public int size() {return this.usedSize;}// 清空顺序表public void clear() {// 由于存放的是基本数据类型,直接清空即可this.usedSize = 0;// 如果存放的是引用数据类型就得通过for循环遍历把数组的内容置为null// 注意:如果直接把数组置为null的话,就会存在安全问题,而且源码也是遍历的方式}
}
 
异常:
PosofAddException:
public class PosofAddException extends RuntimeException{public PosofAddException() {}public PosofAddException(String msg) {super(msg);}
}
 
PosofGetException:
public class PosofGetException extends RuntimeException{public PosofGetException() {}public PosofGetException(String msg) {super(msg);}
} 
PosofSetException:
public class PosofSetException extends RuntimeException{public PosofSetException() {}public PosofSetException(String msg) {super(msg);}
}
 
PosofRemoveException:
public class PosofRemoveException extends RuntimeException{public PosofRemoveException() {}public PosofRemoveException(String msg) {super(msg);}
}
 
分析Java 8 的 ArrayList 的源码
实现了咱们自己写的顺序表了之后,就该来看Java本身的源码是怎么写的以及与我们的有什么不同?(注意:由于Java 17封装性太强,不好观看源码,因此下面的源码来自Java 8。)
字段:

elementData 就是我们自己实现的 elem 数组。
size 就是 usedSize ,也就是这个数组的有效元素的个数。
构造方法:
Java 8 实现的顺序表有三个构造方法。
带有一个 int 类型的参数的构造方法:

不带参数的构造方法:

带一个 Collection 类型的参数的构造方法:
下面的是其源码:

首先,我们得知道Collection 到底是这个啥?

根据上面这个图可以得知:Collection 是一个接口。
上面的参数先不看泛型,那就是Collection c 这个意味着只要实现了Collection 接口,就可以被当成实参传过来。而从上图的关系可知:ArrayList 继承了 AbstractLIst 这个抽象类 ,并且实现了LIst这个接口,而 LIst 这个接口拓展了 Collection 这个接口的功能。也就意味着 ArrayList 这个类实现了 Collection 这个接口。那么 ArrayList 就可以被当成参数传过来。
接下来,就是了解 <? extends E> ,?就可以当成是被传过来的 ArrayList 中的泛型,也就是说被传过来的 ArrayList 中的泛型要是 E 或者 E的子类。例如:

了解了这些,我们就来看源码吧。这个源码的大概意思是把传入的 ArrayList 中的元素给全部拷贝到原来的 ArrayList 的后面。
ArrayList本身的扩容机制和分配内存机制
既然我们在创建一个顺序表的时候,原本是空,那么当我们去增加元素的时候,扩容的机制又是如何呢?

上面是分析过程(可忽略),总之,得出了下面这个结论:
当顺序表为空时,我们如果去增加元素,就会初始化一个大小10的数组。并且数组在满了之后,会按照1.5倍的扩容方式来扩容。如果用户所需大小超过预估1.5倍大小,则按照用户所需大小扩容。
ArrayList常见操作
| boolean add(E e) | 尾插e | 
| void add(int index, E element) | 将 e 插入到 index 位置 | 
| boolean addAll(Collection<? extends E> c) | 将c 中的元素进行尾插 | 
| E remove(int index) | 删除 index 位置元素 | 
| boolean remove(Object o) | 删除遇到的第一个o | 
| E get(int index) | 获取下标index位置元素 | 
| E set(int index, E element) | 将下标 index 位置元素改为 element | 
| void clear() | 清空 | 
| boolean contains(Object o) | 判断是否在顺序表中 | 
| int indexOf(Object o) | 返回第一个o所在下标 | 
| int lastlndexOf(Object o) | 返回最后一个o的下标 | 
| List<E> subList(int fromlndex, int tolndex) | 截取部分list | 
大部分方法,我们都很熟悉。因此这里只展示 addAll()方法 和 subList 方法。

addAll () 方法可以实现 ArrayList 的带Collection 类型的参数的构造方法。
从上面打印的结果可以看出来,ArrayList 是重写了toString 方法的。

从这里我们就可以看出来,被分割的数组应该是下面这样:

ArrayList的遍历
普通for循环遍历
public class Test {public static void main(String[] args) {ArrayList<Integer> arrayList = new ArrayList<>();arrayList.add(1);arrayList.add(2);arrayList.add(3);for (int i = 0; i < arrayList.size(); i++) {System.out.print(arrayList.get(i)+" ");}}
} 
for-each遍历
public class Test {public static void main(String[] args) {ArrayList<Integer> arrayList = new ArrayList<>();arrayList.add(1);arrayList.add(2);arrayList.add(3);for (Integer x : arrayList) {System.out.print(x+" ");}}
} 
toString方法遍历
public class Test {public static void main(String[] args) {ArrayList<Integer> arrayList = new ArrayList<>();arrayList.add(1);arrayList.add(2);arrayList.add(3);System.out.println(arrayList.toString());}
} 
迭代器遍历
public class Test {public static void main(String[] args) {ArrayList<Integer> arrayList = new ArrayList<>();arrayList.add(1);arrayList.add(2);arrayList.add(3);// 调用iterator方法生成一个迭代器,用Iterator<E>来接收Iterator<Integer> integerIterator = arrayList.iterator();// 如果下一个元素有值话,就进入while循环,并且打印下一个值,最后自己往后走while (integerIterator.hasNext()) {System.out.print(integerIterator.next()+" ");}}
} 
只要是实现了 Iterator 接口就可以使用迭代器的方式来遍历。就是下面这张图:

好啦!本期 数据结构之ArrayList与顺序表(上)的学习就到此结束啦!我们下一期再一起学习吧!
相关文章:
数据结构之ArrayList与顺序表(上)
找往期文章包括但不限于本期文章中不懂的知识点: 个人主页:我要学编程(ಥ_ಥ)-CSDN博客 所属专栏:数据结构(Java版) 顺序表的学习,点我 上面这篇博文是关于顺序表的基础知识,以及顺序表的实现。…...
Java 8 中的 Stream API,用于处理集合数据
Java 8 引入了 Stream API,使得处理集合数据变得更加简洁和高效。Stream API 允许开发者以声明式编程风格操作数据集合,而不是使用传统的迭代和条件语句。 一、基本概念 1.1 什么是 Stream Stream 是 Java 8 中的一个新抽象,它允许对集合数…...
106、python-第四阶段-3-设计模式-单例模式
不是单例类,如下: class StrTools():pass str1StrTools() str2StrTools() print(str1) print(str2) 运用单例,先创建一个test.py class StrTools():pass str1StrTools()然后创建一个hello.py,在这个文件中引用test.py中的对象&a…...
【猫狗识别系统】图像识别Python+TensorFlow+卷积神经网络算法+人工智能深度学习
猫狗识别系统。通过TensorFlow搭建MobileNetV2轻量级卷积神经算法网络模型,通过对猫狗的图片数据集进行训练,得到一个进度较高的H5格式的模型文件。然后使用Django框架搭建了一个Web网页端可视化操作界面。实现用户上传一张图片识别其名称。 一、前言 …...
记录汇川:红绿灯与HMI-ST
项目要求: 子程序: 子程序: 实际动作如下: 红绿灯与HMI-ST...
已解决java.nio.charset.CoderMalfunctionError: 编码器故障错误的正确解决方法,亲测有效!!!
已解决java.nio.charset.CoderMalfunctionError: 编码器故障错误的正确解决方法,亲测有效!!! 亲测有效 报错问题解决思路解决方法1. 检查和清理输入数据2. 选择正确的字符集3. 处理异常情况4. 更新Java版本或库5. 检查第三方库的依…...
Linux 中常用的设置、工具和操作
1.设置固定的ip地址步骤 1.1 添加IPADDR“所设置的固定ip地址” TYPE"Ethernet" PROXY_METHOD"none" BROWSER_ONLY"no" BOOTPROTO"static" DEFROUTE"yes" IPV4_FAILURE_FATAL"no" IPV6INIT"yes" IPV6…...
[论文笔记]AIOS: LLM Agent Operating System
引言 这是一篇有意思的论文AIOS: LLM Agent Operating System,把LLM智能体(代理)看成是操作系统。 基于大语言模型(LLMs)的智能代理的集成和部署过程中存在着许多挑战,其中问题包括代理请求在LLM上的次优调度和资源分配,代理和LLM之间在交互…...
2024全国高考作文题解读(文心一言 4.0版本)
新课标I卷 阅读下面的材料,根据要求写作。(60分) 随着互联网的普及、人工智能的应用,越来越多的问题能很快得到答案。那么,我们的问题是否会越来越少? 以上材料引发了你怎样的联想和思考?请写…...
【功能超全】基于OpenCV车牌识别停车场管理系统软件开发【含python源码+PyqtUI界面+功能详解】-车牌识别python 深度学习实战项目
车牌识别基础功能演示 摘要:车牌识别系统(Vehicle License Plate Recognition,VLPR) 是指能够检测到受监控路面的车辆并自动提取车辆牌照信息(含汉字字符、英文字母、阿拉伯数字及号牌颜色)进行处理的技术。车牌识别是现代智能交通…...
TESSENT2024.1安装
一、安装过程参考Calibre安装过程(此处省略,不再赘述) 二、安装license管理器: SiemensLicenseServer_v2.2.1.0_Lnx64_x86-64.bin 三、Patch补丁: tessent安装目录和license管理安装目录,执行FlexNetLic…...
【机器学习】原理与应用场景 Python代码展现
机器学习:原理、应用与实例深度解析 引言一、机器学习的基本原理二、机器学习的应用范围三、机器学习实例解析四、机器学习部分讲解五、机器学习的挑战与未来 引言 随着大数据和计算能力的飞速发展,机器学习(Machine Learning, ML࿰…...
Python怎么循环计数:深入解析与实践
Python怎么循环计数:深入解析与实践 在Python编程中,循环计数是一项基础且重要的技能。无论是处理列表、遍历文件,还是执行重复任务,循环计数都发挥着不可或缺的作用。本文将从四个方面、五个方面、六个方面和七个方面详细阐述Py…...
Facebook企业户 | Facebook公共主页经营
Facebook作为社交媒体巨头,拥有庞大的用户基数,因此,有效经营公共主页是获取持续流量、提升客户信任度和粘性、促进产品或服务销售与转化的关键。要优化Facebook主页,关注以下几点: 1、参与度是关键指标:因…...
排序数组 ---- 分治-归并
题目链接 题目: 分析: 用这道题来回顾一下归并排序的思想找到中间结点, 将数组分成两半, 运用递归的思想, 继续对一半进行分半, 分到最后剩一个元素, 再将左右数组合并, 合并两个有序数组, 是先分解, 再合并的过程在合并两个有序数组时, 需要一个额外的数组来记录, 为了避免每…...
【红黑树变色+旋转】
文章目录 一. 红黑树规则二. 情况一叔叔存在且为红情况二.变色旋旋 一. 红黑树规则 对于红黑树,进行变色旋转处理,终究都是为了维持颜色以下几条规则,只有颜色和规则维持住了,红黑树就维持住了最长路径的长度不超过最短路径的两倍…...
pytorch 使用tensor混合:进行index操作
(Pdb) tmp torch.randn(3,5) (Pdb) indx torch.tensor([1,0]).long() (Pdb) temp(indx) *** NameError: name ‘temp’ is not defined (Pdb) tmp(indx) *** TypeError: ‘Tensor’ object is not callable (Pdb) tmp[indx] tensor([[ 0.1633, 0.9389, 1.2806, -0.2525, 0.28…...
Threejs(WebGL)绘制线段优化:Shader修改gl.LINES模式为gl.LINE_STRIP
目录 背景 思路 Threejs实现 记录每条线的点数 封装原始裁剪索引数据 封装合并几何体的缓冲数据:由裁剪索引组成的 IntArray 守住该有的线段! 修改顶点着色器 修改片元着色器 完整代码 WebGL实现类似功能(简易版,便于测…...
继承-进阶
父子类成员共享 普通成员对象/父子间不共享, 成员独立 函数成员共享(函数不存储在对象中) 子类由两部分构成:父类中继承的成员和子类中新定义成员 继承方式 子类中存在父类private成员但不可直接访问(及时在类中&am…...
探索k8s集群的配置资源(secret和configmap)
目录 ConfigMap ConfigMap(主要是将配置目录或者文件挂载到k8s里面使用) 与Secret类似,区别在于ConfigMap保存的是不需要加密配置的信息。(例如:配置文件) ConfigMap 功能在 Kubernetes1.2 版本中引入&…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...
基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...
安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
