Java数据结构之ArrayList与顺序表

一.线性表

什么是线性表,字面意思,就是可以连成一条线的表,这里的线可以是物理上的一条线,也可以是逻辑上的一条线

物理上的一条线就是类似于数组,即它在内存上是有一块连续的空间,叫做顺序表,如下:

还有一种是逻辑上的一条线,就是再内存中不一定是一段连续的空间,但根据上一个内存可以找到下一块内存,叫做链表,如下:

二.顺序表

今天我们要谈到的ArrayList就是顺序表,也就是说,此ArrayList类的底层是一个数组,它是用数组来组织对象的

三.ArrayList简介

1.它在Java.util包底下,使用时需要导入包

2.它是一个普通的类,实现了List接口;

3.而且他是一个泛型类,要存放什么类型的数据,就要对应传入其包装类,同时在使用时要创建对象

4.它实现了Cloneable接口,表示它可以被克隆;实现了RandomAccess接口,表示可以被随机访问

5.与Vector不同,它不是线程安全的,在单线程情况下可以使用,而在多线程情况下,一般不使用ArrayList

6.它的底层是一个数组,并且可以动态扩容,是可以动态扩容的顺序表

四.ArrayList的使用

1.ArrayList的构造

首先要注意以上这几个成员变量

DEFAULT_CAPACITY是一个默认初始容量

后面这三个数组,前俩个是static final修饰的,属于类独有的,且不可修改(注意,这里的不可修改,只是不可以修改指向,即在内存中的地址,但里面的数可以改)所以内存上独有一份,注意,这俩个数组都没有用到new这个关键字,而且大括号里也没有存放数据,这等同于并没有分配内存!!!

看绿色的英文:We distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when first element is added.指的是,这俩个数组要区分开来,以便知道要添加第一个元素时要扩容多少

最后一个数组elementData是最终存放数据的数组,它暂时也没有指向

看英文,表示这时存储数组列表元素的缓冲区。数组列表的容量为这个数组缓冲区的长度。当添加第一个元素时,elementData=DEFAULT_EMPTY_ELEMENTDATA的空数组将被扩展为DEFAULT_CAPACITY即默认长度

(1).无参构造方法

绿色英文:构造一个空表,并让其初始容量为10

但看代码发现它的初始容量还是0.这是因为,将在第一个添加元素时进行扩容

(2).有参构造方法一

构造一个带有指定容量的数组。

如果传入的初始容量为0,就直接指向那个共有的空数组EMPTY_ELEMENTDATA(这里就和刚才无参的构造方法区分开来了,对于无参构造方法,数组容量初始是0,此个有参构造方法初始容量也是0,但在添加第一个元素时,代码会进行检验,看它们都指向了哪个空数组,如果指向了DEFAULTCAPACITY_EMPTY_ELEMENTDATA,那就会将其扩容为10,如果指向了ELEMPTY_ELEMENTDATA,那就另当别论。)

如果传入的初始容量大于0,那么就会开辟一个新数组,并制定好容量。

(3).有参构造方法二

首先看参数,它必须是一个实现了Collection接口的类,其次,里面传入的数据类型的包装类是继承了E的,E是什么?E是我们的ArrayList里面存放的数据类型的包装类。

然后,c.toArray()可能返回的不是Object类型(这个我会专门写一篇博客来解释),所以可能会进入到第二个if中。而要是初始时c中没有元素,就会直接指向ELEMENTDATA。

2.添加元素

(1).末尾添加元素

先是确定初始容量,第一次添加时可能会涉及到扩容机制(因为如果用了无参构造方法,默认初始容量为10,但还没有分配内存),以第一次添加为例,此时的size就是0,所以传入ensureCapacityInternal的参数就是1:

此时又进入另一个方法,minCapacity是1

这里就把调用哪个构造方法给区分开来了,如果调用了无参构造方法,就会进入if,然后minCapacity就会更新为10,反之直接返回1

explicit表示明确的,就是确定具体的容量。如果minCapacity大于elementData的长度,就会扩容。对于使用了无参构造和使用了传入容量大于1的构造方法的,就会进入if语句,而对于使用了无参构造,以及传入的容量为0或1的,就不会会进入grow方法

对于使用了无参构造的,oldCapacity是0,newCapacity是oldCapacity的1.5倍,这里还是0.进入第一个if之后,newCapacity更新为10!!,然后扩容为10

对于使用了有参构造的,newCapacity更新为1,然后扩容

original就是elementData,newlength就是10或1。newType就是elementData的类型

先看使用了无参构造的,如果elementData是object类型的,就会创建一个新的object数组,长度是10,如果不是object类型,就先更新成object类型,最后将elementData中的元素拷贝到新数组,并且返回

而使用了有参构造的(能进入这一步的,要么是使用了有参构造一且传入的参数为0,要么是有参构造二中掺入一个没有元素的集合,它们的newlength都是1),newlength就是1.

总结:

1.elementData必须是object类,如果不是,就要copy成object,因为由上述代码可看出,所有的操作都是基于object类进行的,因为会涉及到System.arraycopy:

它的参数类型就是object!!!

2.elementData最终不会指向我们最初提到的那俩个static native修饰的数组,由上述add扩容即使可知,只要用到了copyOf方法,就会创建新的对象

3.ArrayList的扩容机制:是1.5倍扩容

(2).指定位置添加元素

(3).将其他集合中的元素添加到ArrayList中

第二个是插入到指定位置

3.删除元素

这个是删除指定下标的元素,注意将末尾元素置为null

这个是删除具体对象,注意用到了对象的比较,equals方法

都调用了fastRemove方法,这个方法相比于remove方法来说,少了一步边界检查,所以叫快速删除

4.clone方法

调用了object类的克隆方法,它的返回值是object,所以要进行向下转型。注意,只进行这一步是不够的,这只是浅拷贝,只进行到了如下图这一步:

它的确是有了一个新的v并且在堆上产生了一个新的对象,但由于调用了copy,所以将原来的数据就元丰不动的拷贝到了新对象上,所以旧的和新的ArrayList对象都指向了0x67这个数组,只是浅拷贝,所以要再进行源码中的数组拷贝,将v对应的对象中的数组在新地址再拷贝一份。

5.ArrayList的遍历

法一:

法二:

法三,用迭代器:

这是源码中生成迭代器的代码,其中ListIterator是一个类,Iterator是一个接口,用哪个都可以

源码中还有一个如下的代码:

这个是可以指定从哪里开始遍历

6.其他方法

subList,返回顺序表中的一部分

还有一些get,set,等方法,看源码就可以看懂

五.ArrayList存在的问题

1.在指定下标添加或删除元素,不仅要遍历数组,还得将剩余数据前移或后移,这导致时间复杂度为O(N)。

2.扩容不是在原始数组上进行,而是申请新的空间,然后拷贝旧数据,最后释放就空间,这样的操作会有很大的资源消耗

3.可能存在空间浪费现象,比如数组长度为100,存放满了,还想再放一个数据,就要1.5倍扩容,此时又多了50个空间,但只用了1个,剩下的就浪费了。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python 中常用的热门库介绍

阅读本文之前请参阅-----如何系统的自学python Python 是一种非常流行的编程语言,它的一个主要优势是拥有一个庞大的生态系统,其中包括许多强大的库。这些库为各种任务提供了解决方案,从数据分析到机器学习,从网络爬虫到图像处理。…

面试数据库篇(mysql)- 02定位慢查询和分析

定位慢查询 聚合查询多表查询表数据量过大查询深度分页查询表象:页面加载过慢、接口压测响应时间过长(超过1s) 方案一:开源工具 调试工具:Arthas 运维工具:Prometheus 、Skywalking 方案二:MySQL自带慢日志 慢查询日志记录了所有执行时间超过指定参数(long_query_tim…

openstack常用查看命令

1.查看所有虚拟机 nova list2.列举某个虚拟机的详细信息 nova show ID3.获取所有服务列表 nova service-list4.查看镜像列表 glance image-list5.查看虚拟机规格信息 nova flavor-list6.查看网络信息 neutron net-list7.查看虚拟机网卡信息 nova interface-list8.查看vnc…

TCP的三次握手和四次挥手 | 查看网络状态

三次握手和四次挥手是在计算机网络中用于建立和终止TCP连接的协议。这两个过程是TCP协议的重要组成部分,确保数据的可靠传输。 三次握手指的是在客户端和服务器之间建立连接时的步骤。具体流程如下: 客户端向服务器发送一个连接请求报文段(…

Promise 介绍与基本使用 - 学习笔记

Promise 介绍与基本使用 1、 Promise 是什么?2、创建 Promise 实例对象3、Promise 实例方法4、Promise 的基本工作流程5、实例方法6、静态方法7、async 和 await7.1、关键字7.2、实例7.3、区别7.4、为什么使用 async/await 比较好? 1、 Promise 是什么&a…

【EI会议征稿通知】2024年第三届生物医学与智能系统国际学术会议(IC-BIS 2024)

2024年第三届生物医学与智能系统国际学术会议(IC-BIS 2024) 2024 3rd International Conference on Biomedical and Intelligent Systems (IC-BIS 2024) 2024年第三届生物医学与智能系统国际学术会议(IC-BIS 2024) 将于2024年4月…

皇冠测评:网络电视盒子哪个品牌好?电视盒子排行榜

欢迎各位来到我们的测评频道,本期我们要分享的产品是电视盒子,因很多网友留言不知道网络电视盒子哪个品牌好,我们通过为期一个月的测评后整理了电视盒子排行榜,想买电视盒子的可以看看下面这五款产品,它们各方面表现非…

CSS_实现三角形和聊天气泡框

如何用css画出一个三角形 1、第一步 写一个正常的盒子模型&#xff0c;先给个正方形的div&#xff0c;便于观察&#xff0c;给div设置宽高和背景颜色 <body><div class"box"></div> </body> <style>.box {width: 100px;height: 100px…

如何使用Windows系统电脑无公网ip远程桌面Ubuntu系统

文章目录 前言1. ubuntu安装VNC2. 设置vnc开机启动3. windows 安装VNC viewer连接工具4. 内网穿透4.1 安装cpolar【支持使用一键脚本命令安装】4.2 创建隧道映射4.3 测试公网远程访问 5. 配置固定TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址5.3 测试…

吴恩达机器学习全课程笔记第四篇

目录 前言 P61-P68 激活函数 Softmax算法 P69-P73 Adam算法 更多类型的层 模型评估 P74-P79 偏差和方差 建立表现基准 学习曲线 偏差和方差与神经网络 前言 这是吴恩达机器学习笔记的第四篇&#xff0c;第三篇笔记请见&#xff1a; 吴恩达机器学习全课程笔记第…

leetcode 重复的子字符串

前要推理 以abababab为例&#xff0c;这里最主要的就是根据相等前后缀进行推导 s [ 0123 ] 如 t【 0123 】 f 【01 23 】 后两个分别是前后缀&#xff0c;第一个是总的字符串&#xff0c;然后可以推导 //首先还是算出…

Fastadmin列表根据status或者固定条件来显示按钮的显示和隐藏

根据订单状态&#xff0c;显示“退款操作”按钮显示和隐藏 打开页面的js文件&#xff0c;在操作的这一列里面再加一个button按钮。也可以新起一列&#xff08;我在其他文章有写&#xff09;添加按钮。 row就是选中的这一些所有的数据。 {field: operate, title: __(Operate…

【c++】stack和queue模拟实现

> 作者简介&#xff1a;დ旧言~&#xff0c;目前大二&#xff0c;现在学习Java&#xff0c;c&#xff0c;c&#xff0c;Python等 > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;能手撕stack和queue模拟 > 毒鸡汤&#xff1a;…

任务系统之API子任务

日常运维工作中有许多的任务要执行&#xff0c;例如项目发布/数据备份/定时巡检/证书更新/漏洞修复等等&#xff0c;大部分的任务都会有多个步骤共同完成&#xff0c;例如一个发布任务会有拉代码、编译、分发、通知等等步骤&#xff0c;而不同的任务可能还包含相同或相似的步骤…

web前端-html自定义列表

html 自定义列表 <!--有序列表 应用范围&#xff1a;试卷、问答--> <ol><li>Java</li><li>C</li><li>Python</li><li>C</li><li>VB</li> </ol><br><!--无序列表 应用范围&#xff1a…

【粉丝福利第一期】小 明

Q1 - 能否自我介绍下&#xff1f; 嗨&#xff0c;大家好&#xff0c;我是 小 明 &#xff08;小明java问道之路&#xff09;&#xff0c;互联网大厂后端研发专家&#xff0c;2022博客之星TOP3/博客专家/CSDN后端内容合伙人、InfoQ(极客时间)签约作者、阿里云签约博主、全网5万…

Apache Paimon Append Queue表解析

a) 定义 在此模式下&#xff0c;将append table视为由bucket分隔的queue。 同一bucket中的每条record都是严格排序的&#xff0c;流式读取将完全按照写入顺序将record传输到下游。 使用此模式&#xff0c;无需特殊配置&#xff0c;所有数据都将作为queue进入一个bucket&…

单/双通道40V 350mA车规级LDO稳压器高集成电流感应调节

概述 PC8803具有高输入电压单低压差调节器&#xff08;PC8803SC01/PC8803SCO3&#xff09;/双通道低压差调节&#xff08;PC8803SC02/PC8803SC04&#xff09;&#xff0c;具有精确的电流感测&#xff0c;设计用于在宽输入电压范围内工作 从4.5V到40V。该设备具有45V负载转储电…

redis中的分布式锁(setIfAbsent)(expire)

目录 应用场景 代码实例1&#xff1a; 代码实例2&#xff1a; setIfAbsent&#xff1a; expire&#xff1a; 举例说明&#xff1a; 代码实例3&#xff1a; 代码实例4&#xff1a; 还是一个同事问的一个问题&#xff0c;然后闲着没事就记录下来了。多人操作同一个保单&a…

智能印刷工厂如何通过引入工业物联网网关实现生产流程的智能化升级-天拓四方

项目背景 某大型印刷企业&#xff0c;面临着市场竞争加剧、生产成本上升和客户对交货时间要求越来越高等多重挑战。为了保持竞争力&#xff0c;该企业决定通过引入工业物联网网关来升级其印刷工厂&#xff0c;实现智能化生产。 应用方案 该企业选择了一款功能强大的工业物联…