数据结构-ArrayLIst-一起探索顺序表的底层实现

ops/2025/1/16 12:03:44/

各位看官早安午安晚安呀

如果您觉得这篇文章对您有帮助的话

欢迎您一键三连,小编尽全力做到更好
欢迎您分享给更多人哦

大家好,我们今天来学习java数据结构的第一章ArrayList(顺序表)

1.ArrayList的概念

那小伙伴就要问了线性表到底是什么呢?
线性表 linear list n 个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列...(我们后续都会进行讲解)
线性表首先是一个序列,也就是说,元素之间是有顺序的,如果元素存在多个,那么第一个元素无前驱。最后一个元素无后驱。其他每个元素都必须有一个前驱和后驱
例如:
usedSize这个变量是非常重要的,我们的增删查改都要用到

1.2ArrayList的模拟实现

java">import java.util.Arrays;public class MyArrayList {private int []elem;//用来存放数据private int usedSize;//非常重要,代表当前顺序表当中的有效数据个数private static final int DEFAULT_SIZE = 2;public MyArrayList() {this.elem = new int[DEFAULT_SIZE];}public MyArrayList(int initCapacity){this.elem = new int[initCapacity];}// 新增元素,默认在数组最后新增public void add(int data) {if(elem.length == usedSize){elem = Arrays.copyOf(elem,elem.length*2);}elem[usedSize] = data;this.usedSize++;//一定不要忘记加}// 在 pos 位置新增元素public void add(int pos, int data) {//只要带pos的都要进行检查if(checkPos(pos) ==false ){return;}if (elem.length == usedSize) {elem = Arrays.copyOf(elem, elem.length * 2);}//下面这种写法就错误了,导致pos后面的值都是pos位置的值/*for (int i = pos; i < usedSize -1; i++) {elem[i+1] = elem[i];}*///应该从后往前for (int i = usedSize-1 ; i >= pos; i--) {elem[i+1] = elem[i];}elem[pos] = data;usedSize++;}/*public void delete(int pos){if(checkPos(pos) == false)if(this.usedSize == 0){System.out.println("数组里面没有元素了");return;}for (int i = 0; i < usedSize - 1; i++) {elem[i] = elem[i+1];}}
*/// 判定是否包含某个元素public boolean contains(int toFind) {//啥意思for (int i = 0; i < usedSize; i++) {if(elem[i] == toFind ) //这里是int类型,所以你能够直接比较,其他类型的话,要重写equals方法return true;}return false;}// 查找某个元素对应的位置public int indexOf(int toFind) {for (int i = 0; i < usedSize; i++) {if(elem[i] == toFind)return i;}System.out.println("没有你要找的值");return -1;}public boolean checkPos(int pos){if( pos < 0 || pos >= usedSize){System.out.println("下标错误");return false;}return true;}// 获取 pos 位置的元素public int get(int pos) {if(checkPos(pos) == false){return -1;}return elem[pos];}// 给 pos 位置的元素设为 valuepublic void set(int pos, int value) {if(checkPos(pos) == false){return;}elem[pos] = value;}//删除第一次出现的关键字keypublic void remove(int data) {int index = this.indexOf(data);if(index == -1){System.out.println("没有这个数据");return;}for (int i = data; i < usedSize - 1; i++) {elem[i] = elem[i+1];}//如果是引用类型的话: elem[index] = null;this.usedSize--;}// 获取顺序表长度public int size() {return this.usedSize;}// 清空顺序表public void clear() {this.usedSize = 0;//但是如果是引用类型的话
/*for (int i = 0; i < usedSize; i++) {elem[i] = null;记得全部置为空引用类型的话,删除也要置为null}
*/}// 打印顺序表,注意:该方法并不是顺序表中的方法,为了方便看测试结果给出的public void display() {for (int i = 0; i < usedSize; i++) {System.out.print(this.elem[i] + " ");}}
}

目前我们自己实现了顺序表这种结构,以后用到的时候,Java已经为我们提供好了

ArrayList(就是一个普通的类实现了List接口)

(自己看一下方法)(ArrayLIst里面的方法,底层方法)(我们可以看出来ArrsyList底层的数组我们在实例化对象时也是默认长度为我们的常量值,有效元素个数非常重要,我们增加删除元素等方法都要用的)

2:构造方法

我们要了解一个类首先要了解他的构造方法

ArrayList<E>中的E就表示列表中存储的元素的类型

ArrayList

2.1:构造方法一,三

java">       ArrayList<Integer> list = new ArrayList<>();   这种能用的方法更多List<Integer> list = new ArrayList<>();    一般我们用这一种,向上转型,动态绑定的等等,你俩用哪个主要看自己业务场景ArrayList<Integer> list = new ArrayList<>(15)

我们可以看到默认数组长度是10,前面源码图解上有

2.2:构造方法二

然后我把list1指定的类型换成Integer就解决问题了!

大家也可以看到我明明对于list3只add了一次但是,打印出来的值却把list1数组里面的内容也拷贝过来了(拷贝在外面构造方法那一步就完成了)

2.3:ArrayList常见操作

java">public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);list.add(1,4);System.out.println(list);//到这里是【1,4,2,3】list.remove(1);//这两个老是搞混,这个是删除1小标的值list.remove(new Integer(1));//要删除1这个元素的值一定要用这种方法,因为这个参数是Object类型的System.out.println(list);//到这里是【2,3】// list.get(2);//这里会报一个数组越界异常,就是用来和UsedSize比较list.add(99);list.add(100);list.add(101);boolean isFalse = list.contains(new Integer(100));//这里最好用Integer类型的System.out.println(isFalse);//trueList<Integer> list1 = list.subList(1,4);//左闭右开System.out.println(list1);list.set(1,200);System.out.println(list);System.out.println(list1);//list1得到的是从list数组里面的引用,只要改变其中一个元素的值,另一个也会改变list.clear();System.out.println(list);//全部清除}

2.4:ArrayList的三种遍历

ArrayList 可以使用三方方式遍历: for 循环 + 下标、 foreach 、使用迭代器
java">public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
// 使用下标+for遍历
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i) + " ");
}
System.out.println();
// 借助foreach遍历
for (Integer integer : list) {
System.out.print(integer + " ");
}
System.out.println();//迭代器
Iterator<Integer> it = list.listIterator();
//ListIterator<Integer> it = list.listIterator();也可以
//ListIterator是Iterator的子类
while(it.hasNext()){
System.out.print(it.next() + " ");
}
System.out.println();
}
注意:
1. ArrayList 最长使用的遍历方式是: for 循环 + 下标 以及 foreach
2. 迭代器是设计模式的一种,后续博客我会继续讲解

2.5:ArrayList的扩容机制的缺陷

ArrayList是一个动态类型的顺序表,即:在插入元素的过程中会自动扩容。以下是ArrayList源码中扩容方式
总结
1. 检测是否真正需要扩容,如果是调用 grow 准备扩容
2. 预估需要库容的大小
初步预估按照 1.5 倍大小扩容 ,如果用户所需大小超过预估1.5 倍大小,则按照用户所需大小扩容
真正扩容之前检测是否能扩容成功,防止太大导致扩容失败
3. 使用 copyOf 进行扩容

3:杨辉三角

力扣杨辉三角

实现:

java">import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Test {public static void main(String[] args) {int num = 5;List<Integer> row = new ArrayList<>();List<List<Integer>> ret = new ArrayList<>();row.add(1);ret.add(row);for (int i = 1; i < num; i++) {List<Integer> curRow1 = new ArrayList<>();curRow1.add(1);//每行的第一个元素都是1List<Integer> previousRow = ret.get(i - 1);for (int j = 1; j < i; j++) {Integer x = previousRow.get(j) + previousRow.get(j - 1);curRow1.add(x);}curRow1.add(1);//每行的最后一个元素也都是1ret.add(curRow1);//把这一行的数组加进去}for (List<Integer>list:ret   //遍历数组) {System.out.println(list);}System.out.println("============================");Iterator<List <Integer>> it = ret.listIterator();//使用迭代器遍历数组
//ListIterator<Integer> it = list.listIterator();也可以
//ListIterator是Iterator的子类while(it.hasNext()){System.out.print(it.next() + " ");System.out.println();}}}

上述就是数据结构-ArrayLIst-数组的深入包装 的全部内容了,能看到这里相信您一定对小编的文章有了一定的认可,数据结构的出现让我们对于数据的组织的利用有了更加方便的使用~~

有什么问题欢迎各位大佬指出
欢迎各位大佬评论区留言修正

您的支持就是我最大的动力​​​!!!!


http://www.ppmy.cn/ops/150548.html

相关文章

两分钟解决 :![rejected] master -> master (fetch first) , 无法正常push到远端库

目录 分析问题的原因解决 分析问题的原因 在git push的时候莫名遇到这种情况 若你在git上修改了如README.md的文件。由于本地是没有README.md文件的&#xff0c;所以导致 远端仓库git和本地不同步。 将远端、本地进行合并就可以很好的解决这个问题 注意&#xff1a;直接git pu…

【漫话机器学习系列】049.集成学习方法(Ensemble Methods)

集成学习方法&#xff08;Ensemble Methods&#xff09; 集成学习&#xff08;Ensemble Learning&#xff09;是一种机器学习方法&#xff0c;通过组合多个模型&#xff08;通常称为基学习器&#xff09;来解决同一任务&#xff0c;从而提高整体性能。其核心思想是&#xff1a…

女性机器人有市场吗

随着AI技术和仿生技术的发展&#xff0c;可以预见&#xff0c;未来的市场上必然出现女性机器人&#xff0c;女性机器人未来会有市场吗&#xff1f;如何定义女性机器人&#xff1f; 1、如果你不想生娃&#xff0c;女性机器人完全可以代替真人。将来的机器人她能干几乎所有的家务…

idea无法下载源码

1. 方式一 在项目下&#xff0c;项目根目录下 或 pom.xml同级目录中执行 mvn dependency:resolve -Dclassifiersources然后点击“download source”时就能看到源码了。

音频DSP的发展历史

音频数字信号处理&#xff08;DSP&#xff09;的发展历史是电子技术、计算机科学和音频工程共同进步的结果。这个领域的进展不仅改变了音乐制作、音频后期制作和通信的方式&#xff0c;也影响了音频设备的设计和功能。以下是对音频DSP发展历史的概述&#xff1a; 早期概念和理论…

Android中下载 HAXM 报错 HAXM installation failed,如何解决?

AMD芯片的电脑在 Android Studio 中安装 Virtual Device 时&#xff0c;经常会出现一个 问题 Intel HAXM installation failed. To install Intel HAXM follow the instructions found at: https://github.com/intel/haxm/wiki/Installation-Instructions-on-Windows 一直提示H…

Web端实时播放RTSP视频流(监控)

一、安装ffmpeg: 1、官网下载FFmpeg: Download FFmpeg 2、点击Windows图标,选第一个:Windows builds from gyan.dev 3、跳转到下载页面: 4、下载后放到合适的位置,不用安装,解压即可: 5、配置path 复制解压后的\bin路径,配置环境变量如图: <

Js:正则表达式及正则表达式方法

① 创建正则表达式对象&#xff1a; /** 语法&#xff1a;* var reg new RegExp(正则表达式, 匹配模式);* 匹配模式(字符串类型)&#xff1a;i --> 忽略大小写 g --> 全局匹配模式*/var reg new RegExp(a, i);var str abc; /** 正则表达式的方法&#…