Java_简单模拟实现ArrayList_学习ArrayList
文章目录
- 一、 了解线性表和顺序表区别
- 1.线性表
- 2.顺序表
- 二、模拟实现
- 1.定义接口
- 2.定义MyArrayList
- 3.成员变量以及构造方法
- 4.实现打印数组
- 5.实现add方法
- 6.实现查找某个数是否存在contains或者某个数的下标indexOf
- 7.获取或更改pos位置的值 get和set
- 8.获取数组大小 size
- 9.删除某个值 remove
- 10.清空 clear
- 三、ArrayList源码如何做的
- 1.成员变量
- 2.构造方法
- 1、有参数的构造
- 2、无参数的构造
- 3、数组构造
- 4.add
- 5.addAll
- 6.remove
- 7.subList
- 8.迭代器 iterator
一、 了解线性表和顺序表区别
1.线性表
线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列…
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。


2.顺序表
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
二、模拟实现
1.定义接口
package mylist;public interface IList {// 新增元素,默认在数组最后新增public void add(int data);// 在 pos 位置新增元素public void add(int pos,int data);//判断是否包含某个元素public boolean contains(int toFind);//查找某一元素的位置public int indexOf(int toFind);//获取pos位置的元素public int get (int pos);//给pos位置元素设为valuepublic void set (int pos,int value);//删除第一次出现的关键字keypublic void remove(int toRemove);//获取顺序表的长豆public int size();//清空顺序表public void clear();//打印顺序表,注意:该方法不是顺序表的方法,为了方便测试结果给出的public void display();}
2.定义MyArrayList
MyArrayList要继承上面的接口并实现,现在是框架。
package mylist;public class MyArrayList implements IList{@Overridepublic void add(int data) {}@Overridepublic void add(int pos, int data) {}@Overridepublic boolean contains(int toFind) {return false;}@Overridepublic int indexOf(int toFind) {return 0;}@Overridepublic int get(int pos) {return 0;}@Overridepublic void set(int pos, int value) {}@Overridepublic void remove(int toRemove) {}@Overridepublic int size() {return 0;}@Overridepublic void clear() {}@Overridepublic void display() {}
}
3.成员变量以及构造方法
//储存元素的数组public int [] elem;//当前顺序表有多少个元素public int usedSize;//默认数组大小public static final int DEFAULT_SIZE = 10;public MyArrayList() {this.elem = new int [DEFAULT_SIZE];}public MyArrayList(int capacity ) {this.elem = new int[capacity];}
4.实现打印数组
public void display() {for(int i = 0;i<usedSize;i++){System.out.print(this.elem[i]+" ");}System.out.print("\n");}
5.实现add方法
在添加之前需要判断是否满(单独将判断是否满方法实现方法名为isFull),如果满了对数组扩容(所以我可以实现检查容量方法,如果满了就扩容,没满就什么都不做),没满添加。
重复上面操作,对于在pos位置添加,要判断pos如果合法就把后面向后挪一位,再对于pos位置添加数据。
不合法抛出异常。
public class PosIllegality extends RuntimeException{public PosIllegality(String msg){super(msg);}
}
---------------------------------------------------------------------------------------public boolean isFull(){if(usedSize>=elem.length){return true;}return false;}private void checkCapacity(){if(isFull()) {//扩容elem = Arrays.copyOf(elem,elem.length*2);}}@Overridepublic void add(int data) {checkCapacity();elem[usedSize++] = data;}private void checkPosOnAdd(int pos){if(pos>usedSize||pos<0){System.out.println("不合法!");throw new PosIllegality("插入元素下标异常"+pos);}}@Overridepublic void add(int pos, int data) {try{checkPosOnAdd(pos);}catch (PosIllegality e){e.printStackTrace();return ;}checkCapacity();for(int i = usedSize++;i>pos;i--){elem[i] = elem[i-1];}elem[pos] = data;}
测试:
public static void main(String[] args) {MyArrayList myArrayList = new MyArrayList();myArrayList.add(1);myArrayList.add(2);myArrayList.add(3);myArrayList.add(4);myArrayList.add(5);myArrayList.add(6);myArrayList.add(7);myArrayList.add(8);myArrayList.add(9);myArrayList.add(10);myArrayList.add(11);myArrayList.add(0,0);myArrayList.add(1,-1);myArrayList.display();}

6.实现查找某个数是否存在contains或者某个数的下标indexOf
首先得判断数组是否为空(可以单独实现是否为空的方法isEmpty),其次再寻找目标数。
注意如果是引用类型,要重写这个方法,比较不能直接比较要调用比较的方法
public boolean isEmpty(){if(usedSize==0){return true;}return false;}@Overridepublic boolean contains(int toFind) {if(isEmpty()){return false;}for(int i = 0;i<usedSize;i++){if(elem[i]==toFind){return true;}}return true;}@Overridepublic int indexOf(int toFind) {if(isEmpty()){return -1;}for(int i = 0;i<usedSize;i++){if(elem[i]==toFind){return i;}}return -1;}
7.获取或更改pos位置的值 get和set
首先检查pos的合法性(单独写个检查pos的方法,如果不合法抛出异常),返回或修改pos位置的值。
private void checkPosOnGet(int pos){if(pos<0||pos>=usedSize){System.out.println("不合法!");throw new PosIllegality("获取元素下标异常"+pos);}}@Overridepublic int get(int pos) {try {checkPosOnGet(pos);}catch (PosIllegality e){e.printStackTrace();return -1;}return elem[pos];}
private void checkPosOnSet(int pos){if(pos<0||pos>=usedSize){throw new PosIllegality("获取元素下标异常"+pos);}}@Overridepublic void set(int pos, int value) {
// try {
// checkPosOnSet(pos);
// }catch (PosIllegality e)
// {
// e.printStackTrace();
// return ;
// }checkPosOnSet(pos);elem[pos] = value;}
8.获取数组大小 size
@Overridepublic int size() {return usedSize;}
9.删除某个值 remove
@Overridepublic void remove(int toRemove) {int index = indexOf(toRemove);if(index==-1){System.out.println("没有这数字");return;}for(int i = index;i<usedSize-1;i++){elem[i] = elem[i+1];}usedSize--;}
10.清空 clear
@Overridepublic void clear() {usedSize = 0;}
思考如果存的是引用数据能不能直接将usedSize=0?
不能如果,数组里面装的是引用数据类型,就会造成内存泄漏。
JVM当中回收算法有很多
当前对象没有人引用的时候(1.elem=null 2.将每一个下标的值 elem[i]=null)
三、ArrayList源码如何做的
1.成员变量

elementData为存储元素的数组,是物理空间连续的内存地址。
size为数组存储元素的个数。
2.构造方法
1、有参数的构造


2、无参数的构造


发现无参数构造不给任何空间,那么add时数据放哪里?
3、数组构造

Collection是什么?
请看下图

? extends E表示:通配符的上级,?是E的子类或本身
举例:
ArrayList list = new ArrayList<>();
ArrayListlist2 = new ArrayList<>(list);
?就表示list的类型Interger,而E就是list2的类型是Number,符合子类。
4.add

这里可以看见add调用了ensureCapacityInternal,size为当前存储的个数当前还是没有任何插入,size为0

minCapacity为1

看上面无参数构造可以知道,if成立,此时返回了默认大小(DEFAULT_CAPACITY)也就是10,返回10。


看下面代码不难发现,grow就是扩容代码,oldCapacity>>1就是除2,ArraryList是1.5倍扩容。

总结:
1、 如果没有分配内存,第一次add会分配大小为10的内存
2、 ArrayList是1 .5倍扩容
5.addAll

public static void main(String[] args) {ArrayList<Integer> arrayList1 =new ArrayList<>();arrayList1.add(1);arrayList1.add(2);arrayList1.add(3);ArrayList<Integer> arrayList2 =new ArrayList<>();arrayList2.add(4);arrayList2.add(5);arrayList2.add(6);arrayList1 .addAll(arrayList2);arrayList2.addAll(1,arrayList1);System.out.println(arrayList1);System.out.println(arrayList2);}

6.remove

注意:传数字,只会删除对应下标的值,而传对象才会删对应的对象。
public static void main(String[] args) {ArrayList<Integer> arrayList1 =new ArrayList<>();arrayList1.add(1);arrayList1.add(2);arrayList1.add(3);arrayList1.remove(2);System.out.println(arrayList1);arrayList1.remove(new Integer(1));System.out.println(arrayList1);}

7.subList

public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);System.out.println(list);List<Integer> list1 = list.subList(1,3);System.out.println(list1);}
注意:
1.为左闭右开
2.返回的位List类型
3.截取不会产生新的对象(对返回的修改,被截取的也会修改)
8.迭代器 iterator
public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);Iterator<Integer> it = list.iterator();while(it.hasNext()){System.out.print(it.next()+" ");}}

相关文章:
Java_简单模拟实现ArrayList_学习ArrayList
文章目录 一、 了解线性表和顺序表区别1.线性表2.顺序表 二、模拟实现1.定义接口2.定义MyArrayList3.成员变量以及构造方法4.实现打印数组5.实现add方法6.实现查找某个数是否存在contains或者某个数的下标indexOf7.获取或更改pos位置的值 get和set8.获取数组大小 size9.删除某个…...
动手学深度学习(一)深度学习介绍2
目录 二、起源 三、深度学习的成功案例: 四、特点: 五、小结: 二、起源 为了解决各种各样的机器学习问题,深度学习提供了强大的工具。 虽然许多深度学习方法都是最近才有重大突破,但使用数据和神经网络编程的核心思…...
vmware网络配置,VMware的三种网络模式详解与配置
vmware为我们提供了三种网络工作模式 vmware为我们提供了三种网络工作模式, 它们分别是: Bridged(桥接模式)、NAT(网络地址转换模式)、Host-Only(仅主机模式)。 VMware虚拟机的三种网络类型的适用场景如下…...
【Ubuntu】安装hbase
前提 需要安装java 安装 HBase 下载并解压 HBase 安装包: wget https://dlcdn.apache.org/hbase/2.5.7/hbase-2.5.7-bin.tar.gz tar -zxvf hbase-2.5.7-bin.tar.gz配置 HBase 环境变量: export HBASE_HOME/path/to/hbase-2.5.7 export PATH$PATH:$H…...
ubuntu16.04环境轻松安装和应用opencv4.9.0(基于源码编译)
目录 一、环境准备 1、安装cmake 2、安装依赖 3、从github上下载opencv4.9.0.zip 二、安装opencv4.9.0 1、解压4.9.0.zip 2、进入build目录编译 3、安装编译好的相关库 4、修改opencv配置文件并使其生效 5、添加PKG_CONFIG路径,并使其生效 三、opencv环境…...
FastBee开源物联网平台2.0开源版发布啦!!!
一、项目介绍 物美智能(wumei-smart)更名为蜂信物联(FastBee)。 FastBee开源物联网平台,简单易用,更适合中小企业和个人学习使用。适用于智能家居、智慧办公、智慧社区、农业监测、水利监测、工业控制等。 系统后端采用Spring boot;前端采用…...
【NeRF和NLP】一些观察感悟,碎碎念
NeRF的paper,有几个感想: NeRF读的时候感觉和diffusion思路特别像,训练目标是一个很小很小的子步骤,大大简化了训练难度NeRF建模的是“真实”世界,其用模型隐含的存储了真实世界的体素(场)模型…...
Python程序设计 基础数据类型
1.1 编程规范 注释 python注释也有自己的规范,在文章中会介绍到。注释可以起到一个备注的作用,团队合作的时候,个人编写的代码经常会被多人调用,为了让别人能更容易理解代码的通途,使用注释是非常有效的。 在说规范…...
浅谈安科瑞智能照明系统在马来西亚国家石油公司项目的应用
摘要:随着社会经济的发展及网络技术、通信技术的提高,人们对照明设计提出了新的要求,它不仅要控制照明光源的发光时间、 亮度,而且与其它系统来配合不同的应用场合做出相应的灯光场景。本文介绍了马亚西亚石油公司智能照明项目的应…...
Java面对对象
Java面向对象 面对对象概述,类与对象,继承,重写与重载,多态,抽象,封装,包,泛型,异常 面对对象概述 什么是面向对象(OOP) 面向对象(Object Ori…...
代码随想录算法训练营|day24
第七章 回溯算法 77.组合代码随想录文章详解总结 77.组合 以n5,k3为例 (1)for循环遍历,递归选择符合要求的值加入path,len(path)k时,返回 statrtIndex保证每次递归取到的值不重复 剪枝:i<n-(k-len(path))1 后续需要k-len(pat…...
嵌入式学习日记 16
共用体 union 共用体名 { 成员列表; //各个变量 }; //表示定义一个共用体类型 注意: 1.共用体 初始化 --- 只能给一个值,默认是给到第一个成员变量的 2.共用体成员变量辅助 共用体用的数据最终存储的 --- 应该是最后一次给到的值。 但是只能…...
【Vue.js设计与实现】第一篇:框架设计概览-阅读笔记(完结)
从高层设计的角度去探讨框架需要关注的问题。 参考:速读《Vue.js 设计与实现》 - 掘金 (juejin.cn) 系列目录: 标题博客第一篇:框架设计概览【Vue.js设计与实现】第一篇:框架设计概览-阅读笔记第二篇:响应系统【Vue.…...
数据结构—动态查找表
动态查找介绍 1. 动态查找的引入:当查找表以线性表的形式组织时,若对查找表进行插入、删除或排序操作,就必须移动大量的记录,当记录数很多时,这种移动的代价很大。 2. 动态查找表的设计思想:表结构本身是…...
Hbase-2.4.11_hadoop-3.1.3集群_大数据集群_SSH修改默认端口22为其他端口---记录025_大数据工作笔记0185
其实修改起来非常简单,但是在大数据集群中,使用到了很多的脚步,也需要修改, 这里把,大数据集群,整体如何修改SSH端口,为22022,进行总结一下: 0.hbase-2.4.11的话,hbase集群修改默认SSH端口22,修改成22022,需要修改 需要修改/opt/module/hbase-2.4.11/conf/hbase-env.sh 这里…...
c++学习第十四讲---STL常用容器---vector容器
vector容器: 1.vector基本概念: vector功能与数组类似,与数组不同的是,vector可以动态扩展。 2.vector构造函数: vector<T> v; //默认构造函数,创建数据类型T的容器 ve…...
数据结构-内部排序
简介 排序(Sorting):将一个数据元素(或记录)的任意序列,重新排列成一个按关键字有序的序列 排序算法分为内部排序和外部排序 内部排序:在排序期间数据对象全部存放在内存的排序 外部排序&am…...
Qt加载网页崩溃 ASSERT:“m_adapterClient“ in file ...
1、软件启动后加载网页无异常,点击按钮,加载新网页时崩溃 崩溃代码: QWebEngineView *createWindow(QWebEnginePage::WebWindowType type) { Q_UNUSED(type); return this; } 2、原因 Qt只是调用谷歌的浏览器引擎ÿ…...
合约短线高胜率策略-扭转乾坤指标使用说明
扭转乾坤指标使用说明 行情判断 双绿线 多趋势双红线 空趋势大绿线 小红线 多震荡大红线 小绿线 空震荡 进场条件 趋势行情进场 多趋势 多信号 底金叉 做多空趋势 空信号 顶死叉 做空 震荡行情进场 多震荡 多信号 底金叉 做多多震荡 空信号 顶死叉 做空空…...
DAY37:贪心算法738
今天写了一道题目,顺便看了一个很好的总结,这篇博客可以跳过。 Leetcode:738 单调递增的数字 因为最大的数字是9,当出现后面位数的数字比前面位数的数字小的时候,就把后面的数字都变成9,前面那个数字--。…...
Hugo-PaperMod导航菜单异常修复:从故障诊断到性能优化全指南
Hugo-PaperMod导航菜单异常修复:从故障诊断到性能优化全指南 【免费下载链接】hugo-PaperMod A fast, clean, responsive Hugo theme. 项目地址: https://gitcode.com/GitHub_Trending/hu/hugo-PaperMod Hugo-PaperMod作为一款轻量级响应式主题,…...
AnimateDiff部署指南:SD1.5+Motion Adapter显存优化版保姆级教程
AnimateDiff部署指南:SD1.5Motion Adapter显存优化版保姆级教程 1. 项目简介 想用几句话就让AI帮你生成一段流畅的视频吗?AnimateDiff就是这样一个神奇的工具。与那些需要你先提供一张图片才能生成视频的模型不同,AnimateDiff可以直接根据你…...
FireRed-OCR StudioGPU适配方案:多卡并行解析长文档的配置详解
FireRed-OCR StudioGPU适配方案:多卡并行解析长文档的配置详解 1. 工业级文档解析工具概述 FireRed-OCR Studio是一款基于Qwen3-VL模型开发的下一代文档解析工具,专为处理复杂文档场景设计。它不仅能够精准识别文字内容,更能完整还原文档中…...
深度解析Wiki.js操作日志系统:构建企业级安全监控的完整方案
深度解析Wiki.js操作日志系统:构建企业级安全监控的完整方案 【免费下载链接】wiki- Wiki.js | A modern and powerful wiki app built on Node.js 项目地址: https://gitcode.com/GitHub_Trending/wiki78/wiki- 当团队协作编辑Wiki内容时,你是否…...
从立创EDA到Cadence Allegro:封装转换的完整指南
1. 为什么需要封装转换? 最近在帮朋友做一个硬件项目,发现他用立创EDA设计的电路板需要转到Cadence Allegro平台生产。这就像两个说不同语言的人要合作,必须找个翻译——封装转换就是这个翻译过程。立创EDA和Allegro虽然都是PCB设计工具&…...
SolidWorks装配体设计必备:如何用草图投影实现零件快速匹配(2023最新版)
SolidWorks装配体设计效率革命:草图投影的进阶应用与实战技巧 在三维机械设计领域,装配体设计往往是最考验工程师功底的环节。当数十甚至上百个零件需要在虚拟空间中精确配合时,传统逐个修改零件的方法不仅效率低下,还容易产生累积…...
AI专著写作指南:深度剖析热门工具,助你专著创作一步到位
撰写学术专著的挑战与AI解决方案 撰写学术专著是一项严峻的挑战,它不仅考验着研究者的学术能力,还对心理承受能力提出了很高的要求。与论文写作常常可以依赖团队的支持不同,专著的创作更多的是独立作战。从选题到框架设计,再到细…...
Docker构建速度太慢?试试替换Debian基础镜像的APT源为阿里云(附多版本Dockerfile写法)
加速Docker构建:Debian基础镜像APT源优化全指南 每次等待Docker镜像构建完成时,看着缓慢下载的进度条,是不是感觉时间仿佛被拉长了?特别是在国内网络环境下,从官方Debian源拉取软件包的速度简直让人抓狂。我曾经的一个…...
CVPR/ICML/TMI顶会风向标:医学图像分割三大落地范式,从模型精调到临床闭环
1. 医学图像分割的临床落地挑战与范式转变 医学图像分割作为AI在医疗领域最成熟的应用之一,正经历着从实验室精度竞赛到临床实用落地的关键转型。我在参与多家三甲医院PACS系统智能化改造时发现,临床医生对算法的需求呈现明显的"三高"特征&…...
SegFormer源码解读:从注意力机制到特征融合的实现细节
SegFormer源码解读:从注意力机制到特征融合的实现细节 【免费下载链接】SegFormer Official PyTorch implementation of SegFormer 项目地址: https://gitcode.com/gh_mirrors/se/SegFormer SegFormer是一个基于Transformer的语义分割模型,它通过…...
