ArrayList与顺序表(2)

 前言~🥳🎉🎉🎉  

hellohello~,大家好💕💕,这里是E绵绵呀✋✋ ,如果觉得这篇文章还不错的话还请点赞❤️❤️收藏💞 💞 关注💥💥,如果发现这篇文章有问题的话,欢迎各位评论留言指正,大家一起加油!一起chin up!👍👍 

💥个人主页:E绵绵的博客
💥所属专栏:JAVA知识点专栏   JAVA题目练习  c语言知识点专栏   c语言题目练习

在上一章我们将顺序表的模拟讲了之后,我们现在正式开始介绍ArrayList这个类(顺序表)。开始吧! 


参考文章:【Java 数据结构】顺序表_数据结构java顺序表基本算法测试-CSDN博客

ArrayList的介绍 

 在集合框架中,ArrayList是一个普通的类,实现了List接口,具体框架图如下:

❤️❤️由这可知:

1. ArrayList是以泛型方式实现的,所以使用时必须要先实例化

2. ArrayList实现了RandomAccess接口,表明ArrayList支持随机访问

3. ArrayList实现了Cloneable接口,表明ArrayList是可以clone的

4. ArrayList实现了Serializable接口,表明ArrayList是支持序列化的

5. 和Vector不同,ArrayList不是线程安全的,在单线程下可以使用,在多线程中可以选择Vector或者 CopyOnWriteArrayList

6. ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表


我们查看源码可知的确实施了这些接口。

这就是类定义的前部分,这里还是比较复杂的,会随着我们学习的深入,逐步学习到。

❤️❤️接下来我们来看ArrayList的几个成员变量:



对于第一个成员变量,我们无需了解,只需要关注下后面五个成员变量。

 使用ArrayList


 ArrayList的构造方法 


 第一个构造方法

当前是一个带参数的构造方法,很好理解,根据传递的参数开辟数组空间的大小。如果参数是等于0,就直接把 EMPTY_ELEMENTDATA 这个空数组赋值给存放数据的数组中。 如果是给定一个负数,显然是错误的,也即直接抛出异常!

第二个构造方法 


对于这个无参构造方法居然也是给了一个空数组,也就是没有分配数组内存,那它到底是怎么把数据放进去的?别急,随着后面的讲解,我们会解开这个谜题。

第三个构造方法 

 


里面涉及了泛型的进阶,我们这也不怎么好描述,就直接说特点吧:

下面是这个构造方法的一些特点:

参数c要求是实现了Collection接口的对象,

参数c中的<>元素类型必须与ArrayList中的<>元素类型兼容,即参数c中的<>元素类型必须是ArrayList中<>元素类型的子类或者相同类型。

在使用该构造方法后,它会按照参数c中元素的顺序将元素添加到新创建的ArrayList中。

实例如下:

public class Test {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("apple");list.add("banana");list.add("orange");ArrayList<String> arrayList = new ArrayList<>(list);System.out.println(arrayList);}}


所以由这可知我们就将list内部的元素apple banana orange全部复制到Arraylist内部中(按顺序复制)。

ArrayList中的tostring方法 

由上图可知我们的ArrayList重写了toString方法。所以在用println时,内部参数为ArrayList对象时其将打印出该对象内部的所有元素,以字符串形式打印出来。

例如,如果ArrayList中有三个元素 “apple”、“banana” 和 “orange”,那么调用println方法将打印出字符串 “[apple, banana, orange]”。

ArrayList 的 add 方法 


别小看这几行代码,跟我们自己模拟实现的还是有区别的,真正有内涵的代码其实在 ensureCapacityInternal 这个方法中,那么现在,我们就一步步去解开他的面纱:

由这可知,我们就可以解开之前构造方法中的问题:我们用无参构造方法给其elementData一个空数组,也就是没有分配内存,那么它到底怎么存放数据进去?


我们看源码可知如果在使用add时elementData指向一个空数组,那么在使用add方法时内部的ensureCapacityInternal方法会给其element重新指向一个可以存放十个数据的数组,这样就可以存放数据了。


我们还从源码处可知在使用add时如果其数组中的数据已经满了,那么其会为该数组扩容1.5倍再存放数据。


所以这就是add的厉害之处。不仅能给内部为空数组的ArrayList对象重新开辟一个内部为10个数据的数组,使其能存放数据; 它还可以为满数据的数组实现扩容,使其也能存放数据。

 ArrayList的常用方法


在这里我们就重点讲两个方法 addAll和subList,

❤️❤️对于其他方法的使用,都很简单,自己去查源码,我这就不讲了。到了数据结构阶段,就要尝试着自己看源码,培养自主学习的能力!

 addAll方法

ArrayList中的addAll方法是用于将另一个集合c中的所有元素添加到当前ArrayList对象中的方法。它的语法如下:

boolean addAll(Collection<? extends E> c)

其中有以下要求:

参数c要求是实现了Collection接口的对象,

参数c中的<>元素类型必须与ArrayList中的<>元素类型兼容,即参数c中的<>元素类型必须是ArrayList中<>元素类型的子类或者相同类型。


这个方法可以用于批量添加元素到ArrayList对象中,方便快捷。注意,addAll方法不会去重,如果添加的元素在当前ArrayList中已经存在,则会重复添加

 subList方法

ArrayList中的subList方法用于获取原顺序表的一个子顺序表。它接受两个参数,分别是起始索引(fromindex)和结束索引(toindex),其左闭右开。一个新的List对象,包含原顺序表中指定范围内的元素。


subList方法返回的子顺序表在原顺序表的内部,对子顺序表的修改会反映到原顺序表上,反之亦然。这意味着,如果你修改了子顺序表中的元素,原顺序表也会相应地被修改;如果你修改了原顺序表中的元素,子顺序表也会相应地被修改。


需要注意的是,如果有一个顺序表此时存在一个子顺序表,现在将该顺序表结构性修改(如添加或删除元素),之后再用println打印子顺序表,会导致ConcurrentModificationException异常抛出。这是因为结构性修改改变了原顺序表的大小,从而也破坏了其子列表的大小,所以打印子列表时就报错。(内容牵涉到了迭代器,这里就不细讲)


ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);List<Integer> subList = list.subList(1, 4);
System.out.println(subList);  // 输出:[2, 3, 4]subList.set(0, 10);
System.out.println(list);  // 输出:[1, 10, 3, 4, 5]list.add(6);
System.out.println(subList);  // 抛出ConcurrentModificationException异常

ArrayList的常用方法总使用 

 ❤️❤️以下是我们对常用方法的总使用,大家了解一下。

        ArrayList<Integer> arrayList = new ArrayList<>();// 1,插入(尾插)arrayList.add(1);arrayList.add(2);arrayList.add(3);arrayList.add(4);arrayList.add(5);System.out.println("插入数据后:" + arrayList);// 2,在任意位置插(下标)插入arrayList.add(0, -1);System.out.println("在0下标插入-1后:" + arrayList);// new 一个链表对象并尾插“1”,“2”LinkedList<Integer> linkedList = new LinkedList<>();linkedList.addLast(1);linkedList.addLast(2);// 3,插入 linklist 的所有元素arrayList.addAll(linkedList);System.out.println("插入linklist后:" + arrayList);// 4,删除任意位置(下标)数据arrayList.remove(0);System.out.println("删除0下标数据后:" + arrayList);// 5,删除指定数据arrayList.remove(new Integer(1));// 参数为Object(类)类型的对象System.out.println("删除第一个1后:" + arrayList);// 上面两个remove()方法构成了重载// remove()方法的参数如果输入整数之后不会自动装箱,而是会被自动识别为index。// 因为index是int类型,而顺序表中的数据是Object(类)类型// 但在插入数据时,输入的是1,基本类型,它会自动装箱,变成Integer类型//删除数据时之所以输入整数时不自动装箱是因为其参数本身就有index(整数)这个类型//所以优先选择该整型参数,不会自动装箱。// 所以要删除数据,应该输入类类型的对象,而不是基本类型的数据// 6,获取任意位置(下标)数据int ret = arrayList.get(0);System.out.println("得到0下标的数据:" + ret);// 7,更改任意位置(下标)数据arrayList.set(0,100);System.out.println("把0下标数据改成100后:" + arrayList);// 8,判断是否存在该数据boolean bl = arrayList.contains(100);System.out.println("判断是否存在100这个数据:" + bl);// 9,返回第一个key的位置(下标)int index = arrayList.indexOf(2);System.out.println("第一个2的下标:" + index);// 10,返回最后一个key的位置(下标)int lastIndex = arrayList.lastIndexOf(2);System.out.println("最后一个2的下标:" + lastIndex);// 11,获取顺序表长度int size = arrayList.size();System.out.println("顺序表长度为:" + size);// 12,截取List<Integer> list  = arrayList.subList(1, 3);// [1,3)左闭右开,返回出的子顺序表和ArrayList共用一个elementData数组System.out.println(list);// 13,清空顺序表arrayList.clear();System.out.println("清空顺序表后:" + arrayList);

ArrayList的遍历 

 ❤️❤️对于顺序表的遍历,我们可以通过 for 循环,for-each,以及迭代器的方法遍历:

public class TestArrayList {public static void main(String[] args) {ArrayList<Integer> arrayList = new ArrayList<>();arrayList.add(1);arrayList.add(2);arrayList.add(3);// 通过for循环遍历ArrayListfor (int i = 0; i < arrayList.size(); i++) {System.out.print(arrayList.get(i) + " ");}// 通过for-each循环遍历ArrayListfor (Integer integer : arrayList) {System.out.print(integer + " ");}// 通过迭代器遍历ArrayList(了解即可,无需深入了解,之后会学)Iterator<Integer> it = arrayList.iterator();while (it.hasNext()) {System.out.print(it.next() + " ");}}
}

除此以外,我们还可以通过println(ArrayList对象)打印出该对象内部的所有元素,这个方法我们在之前就讲过了,这里不多讲述了。

 总结

所以对于我们的顺序表的相关知识点就讲完啦,之后将给大家介绍链表,敬请期待! 还希望各位大佬们能给个三连,点点关注,点点赞,发发评论呀,感谢各位大佬~❤️❤️💕💕🥳🎉🎉🎉

 

 

 

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

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

相关文章

归并排序精讲

一.定义 归并排序&#xff08;Merge sort&#xff09;是建立在归并操作上的一种有效的排序算法&#xff0c;该算法是采用分治法&#xff08;Divide and Conquer&#xff09;的一个非常典型的应用。将已有序的子序列合并&#xff0c;得到完全有序的序列&#xff1b;即先使每个子…

C++ 虚表起源

本文会让看不见 摸不着的虚表(Vtable),虚指针(Vptr)彻底现行 本文涉及思想: C 面向对象 封装 继承 多态 中的 多态 概念解释: 虚表指针&#xff1a; 这是指向虚表&#xff08;vtable&#xff09;的指针&#xff0c;虚表中包含了该类的所有虚函数对应的地址。 虚表&#x…

外贸客户开发有用的软件

外贸客户开发过程中&#xff0c;选择合适的软件工具能够显著提升效率和效果。以下是一些对外贸客户开发非常有用的软件&#xff1a; CRM系统&#xff1a; Salesforce&#xff1a;全球领先的CRM平台&#xff0c;提供强大的客户关系管理、市场分析、销售自动化等功能&#xff0c;…

vue基础语法学习

Object.defineProperty方法的使用 // 这是一个普通的对象 let phone {} // 给这个phone新增一个属性 三个参数&#xff1a;新增属性的对象&#xff0c;新增啥属性&#xff0c;属性值&#xff0c;key value对 Object.defineProperty(phone,color,{value:太空灰, //设置属性值wr…

Axure糖尿病健康管理APP原型 (知识科普/病友社区/远程医生会诊/购物商城/血糖监测/饮食监测)

作品概况 页面数量&#xff1a;共 50 页 源文件格式&#xff1a;rp格式&#xff0c;兼容 Axure RP 9/10&#xff0c;非程序软件无源代码 应用领域&#xff1a;医疗健康、慢病管理、糖尿病管理 作品特色 本作品为Axure糖尿病健康管理APP端原型图&#xff0c;设计规范内容清晰…

深度解读《深度探索C++对象模型》之C++虚函数实现分析(一)

目录 成员函数种类 虚函数的实现 单一继承下的虚函数 接下来我将持续更新“深度解读《深度探索C对象模型》”系列&#xff0c;敬请期待&#xff0c;欢迎关注&#xff01;也可以关注公众号&#xff1a;iShare爱分享&#xff0c;或文章末尾扫描二维码&#xff0c;自动获得推文…

邮件接口的安全性如何保障?如何有效使用?

邮件接口故障时如何处理&#xff1f;怎么设置和配置邮件接口&#xff1f; 邮件接口作为企业内外部沟通的重要桥梁&#xff0c;其安全性显得尤为重要。那么&#xff0c;邮件接口的安全问题如何保障。AokSend将深入探讨如何保障邮件接口的安全性&#xff0c;确保企业信息的安全传…

什么是仪器校准报告?

在科学实验和工业生产中&#xff0c;仪器是一种非常重要的辅助工具&#xff0c;无论是测量数据、控制实验进程还是保证产品质量&#xff0c;仪器都发挥着至关重要的作用。为了确保仪器的准确性和稳定性&#xff0c;仪器校准报告这一概念应运而生。本文给大家详细介绍仪器校准报…

科研基础与工具(论文写作)

免责申明&#xff1a; 本文内容只是学习笔记&#xff0c;不代表个人观点&#xff0c;希望各位看官自行甄别 参考文献 科研基础与工具&#xff08;YouTube&#xff09; 学术写作句型 Academic Phrase bank 曼彻斯特大学维护的一个网站 写论文的时候&#xff0c;不不知道怎么…

简单使用Web3.js

随着区块链技术的快速发展&#xff0c;以太坊&#xff08;Ethereum&#xff09;作为其中的佼佼者&#xff0c;为开发者们提供了一个构建去中心化应用的强大平台。为了更轻松地与以太坊区块链进行交互&#xff0c;我们需要一个强大的工具&#xff0c;而Web3.js正是这样一个工具。…

【Linux】IO多路转接技术Epoll的使用

【Linux】IO多路转接技术Epoll的使用 文章目录 【Linux】IO多路转接技术Epoll的使用前言正文接口介绍工作原理LT模式与ET模式边缘触发&#xff08;ET&#xff09;水平触发&#xff08;LT&#xff09; 理解ET模式和非阻塞文件描述符ET模式epoll实现TCP服务器简单地封装epoll系统…

【软件测试】认识测试|测试岗位|软件测试和开发的区别|优秀的测试人员需要具备的素质

一、什么是测试 测试在⽣活中处处可⻅ 1.生活中的测试场景 案例⼀&#xff1a;对某款购物软件进⾏测试 *启动测试&#xff1a;点击软件图标&#xff0c;测试软件是否可以正常打开 搜索测试&#xff1a;点击输入框&#xff0c;输入关键词&#xff0c;点击搜索 商品测试&#…

【数据结构】图论(图的储存方式,图的遍历算法DFS和BFS、图的遍历算法的应用、图的连通性问题)

目录 图论一、 图的基本概念和术语二、图的存储结构1. 数组(邻接矩阵)存储表示无向图的数组(邻接矩阵)存储表示有向图的数组(邻接矩阵)存储表示 邻接表存储表示有向图的十字链表存储表示无向图的邻接多重表存储表示 三、图的遍历算法图的遍历——深度优先搜索&#xff08;DFS&a…

.net core webapi 添加日志管理看板LogDashboard

.net core webapi 添加日志管理看板LogDashboard 添加权限管理&#xff1a; 我们用的是Nlog文件来配置 <?xml version"1.0" encoding"utf-8" ?> <nlog xmlns"http://www.nlog-project.org/schemas/NLog.xsd"xmlns:xsi"http:/…

软考高项(已通过,E类人才)-学习笔记材料梳理汇总

软考高项&#xff0c;即软考高级信息系统项目管理师&#xff0c;全国计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试中的高级水平测试。适用于从事计算机应用技术、软件、网络、信息系统和信息服务等领域的专业人员&#xff0c;以及各级企业管理人员和从事项目…

Netty学习——实战篇7 ProtoBuf实战-多类型数据

1 需求&#xff1a; 1、客户端可以随机发送Student POJO 、Worker POJO 对象到服务器(通过protobuf编码) 2、服务端能接收 Student POJO 、Worker POJO 对象(需要判断是哪种类型)&#xff0c;并显示信息(通过ProtoBuf解码) 2 开发 2.1 编写proto文件 MyDate.proto syntax &…

力扣练习题(2024/4/18)

1不相交的线 在两条独立的水平线上按给定的顺序写下 nums1 和 nums2 中的整数。 现在&#xff0c;可以绘制一些连接两个数字 nums1[i] 和 nums2[j] 的直线&#xff0c;这些直线需要同时满足&#xff1a; nums1[i] nums2[j]且绘制的直线不与任何其他连线&#xff08;非水平线…

省级客运、货运量及周转量数据(1990-2022年)

1、数据介绍 客运量和货运量是衡量交通运输行业发展状况的重要指标&#xff0c;可以反映一个地区或国家的经济发展水平和人民生活水平。而周转量则是反映运输行业效率的指标&#xff0c;即货物或旅客被运输的总距离。 省级客运、货运量及周转量是衡量一个地区交通运输行业发展…

Excel如何计算时间差

HOUR(B1-A1)&"小时 "&MINUTE(B1-A1)&"分钟 "&SECOND(B1-A1)&"秒"

手拉手安装Kafka2.13发送和消费消息

Kafka是一种高吞吐量的分布式发布订阅消息系统&#xff0c;它可以处理消费者在网站中的所有动作流数据。 Kafka启动方式有Zookeeper和Kraft&#xff0c;两种方式只能选择其中一种启动&#xff0c;不能同时使用。 Kafka下载https://downloads.apache.org/kafka/3.7.0/kafka_2.…