ArrayList源码实现(一)

ArrayList源码实现(一)

1. ArrayList的大小是如何自动增加的?

  • 初始化
    • 在构造函数中,可以设定列表的初始值大小,如果没有的话默认使用,提供的静态数据
 public ArrayList(int initialCapacity) {if (initialCapacity > 0) {this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {this.elementData = EMPTY_ELEMENTDATA;} else {throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}}

注意:elementData 变量是 transient 关键字修饰的。

  • 动态扩容

重点关注 ensureCapacityInternal 函数,

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
实际的扩容函数
在这里插入图片描述

在这里插入图片描述

总结:在每次添加add 新的数据时,会进行一次 数组长度大小 的判断;

  1. 如果是数组为 空 时,最小长度就是 10,否则的话,带扩容的最小长度时 size(此时保存了多少数据)+1 (*calculateCapacity*
  2. 当最小容量 大于 数组的总长度时,进行扩容(ensureExplicitCapacity
  3. 数组的最大长度就是 Integer.*MAX_VALUE*
  4. 注意:扩容是创建了一个新的数组,将 elementData 指向了新的数组(elementData = Arrays.*copyOf*(elementData, newCapacity);

2. ArrayList的增加或者删除某个对象的对象为什么效率很低?

在ArraysList中 add、addAll与remove等方法,底层主要依赖于 System.*arraycopy ,这个是一个*native 方法,在ArrayList 对外提供的方法中,大量的使用了这个API,当频繁的对列表中的元素进行 add/remove 操作是,会比较费资源。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

附录

1. transient 是什么

transient 关键字在 Java 中的作用是指定某个类的成员变量不参与序列化过程。序列化是将对象的状态转换为字节流的过程,常用于将对象保存到文件中或通过网络传输。而使用 transient 关键字修饰的变量在对象被序列化时不会被保存,这样可以防止不必要或敏感的数据被序列化。

具体作用如下:

  1. 防止序列化敏感数据:某些类的字段可能包含敏感数据(如密码、个人信息),你不希望它们被序列化并保存到磁盘或通过网络传输。在这种情况下,可以使用 transient 关键字修饰该字段,序列化时就会跳过这个字段。
  2. 节省存储空间:对于某些不需要序列化的字段(例如缓存、临时变量等),使用 transient 可以避免不必要的数据占用存储空间。
  3. 防止不合法的数据:某些字段可能在对象被反序列化之后重新计算或初始化,如果这些字段被序列化了,可能会导致不合法的状态。在这种情况下,也可以使用 transient 来避免这些字段的序列化。

2. list中定义的最大长度为什么会减8

/**
* The maximum size of array to allocate.
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8 的设置是为了处理 JVM 中数组分配的一些特定限制和内存管理问题。Integer.MAX_VALUE2^31 - 1,即 2147483647,是 Java 中 int 类型的最大值。但在实际中,JVM 为数组分配内存时,最大数组大小会比这个理论值略小。以下是为什么减去 8 的原因:

原因分析:

  1. JVM 的内存管理和数组头部
    • 在 JVM 中,数组对象除了存储数组的数据本身外,还需要存储一些额外的信息,比如数组的长度、类型信息等。这些信息占用了一部分内存,通常被称为数组的头部(header words)。
    • 具体需要多少字节来存储这些头部信息,依赖于 JVM 实现和对象内存布局。虽然不同 JVM 实现可能有所不同,但大多数 JVM 可能会保留几个字节(如 8 字节)用于这部分元数据。
  2. 避免 OutOfMemoryError
    • 通过减去 8,确保在数组分配时有足够的空间容纳这些头部信息,避免超出 JVM 对数组对象大小的限制。如果不进行这个调整,分配接近 Integer.MAX_VALUE 大小的数组可能会导致 OutOfMemoryError,因为 JVM 不能同时为数据和头部信息分配足够的内存。
    • 这个限制还可以避免一些边界情况下的问题,比如内存碎片或者其他 JVM 的内部管理机制的需求。
  3. 系统和实现的差异
    • 不同的 JVM 和平台可能有不同的数组大小限制。尽管理论上 Java 数组可以拥有 Integer.MAX_VALUE 个元素(即 2147483647 个),但在实际中,JVM 往往需要一些额外的空间来管理数组的结构。因此,MAX_ARRAY_SIZE 设置为 Integer.MAX_VALUE - 8 是一个安全边界,可以确保数组不会因为接近最大值而触发异常。

总结:

MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8 是为了确保在 JVM 中分配接近最大容量的数组时,不会因为数组头部信息或 JVM 内存管理的限制而导致 OutOfMemoryError。减去的 8 字节主要是预留给数组的头部信息或其他内存管理开销。

3. System.arraycopy 方法

System.arraycopy(a, 0, elementData, size, numNew) 是 Java 中用于执行数组复制的代码,使用了 System.arraycopy 方法。这个方法能够快速、高效地复制数组中的元素。让我们详细解释这个调用的作用:

参数解析:


System.arraycopy(a, 0, elementData, size, numNew);
  1. a:源数组,表示要从中复制元素的数组。
  2. 0:源数组 a 中复制的起始位置,表示从 a 数组的第一个元素(索引 0)开始复制。
  3. elementData:目标数组,表示将元素复制到的数组。
  4. size:目标数组 elementData 中开始粘贴元素的位置,表示将从目标数组的 size 索引开始粘贴数据。
  5. numNew:要复制的元素数量,表示从源数组 a 中复制多少个元素到目标数组。

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

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

相关文章

RabbitMQ应用

RabbitMQ 共提供了7种⼯作模式, 进⾏消息传递 一、七种模式的概述 1、Simple(简单模式) P:生产者,就是发送消息的程序 C:消费者,就是接收消息的程序 Queue:消息队列,类似⼀个邮箱, 可以缓存消息; ⽣产者…

UniApp基于xe-upload实现文件上传组件

xe-upload地址:文件选择、文件上传组件(图片,视频,文件等) - DCloud 插件市场 致敬开发者!!! 感觉好用的话,给xe-upload的作者一个好评 背景:开发中经常会有…

几个可以给pdf加密的方法,pdf加密详细教程。

几个可以给pdf加密的方法,pdf加密详细教程。在信息快速传播的今天,PDF文件已经成为重要的文档格式,被广泛应用于工作、学习和个人事务中。然而,随着数字内容的增加,数据安全和隐私保护的问题愈发凸显。无论是商业机密、…

CAT1 RTU软硬件设计开源资料分析(TCP协议+Modbus协议+GNSS定位版本 )

01 CAT1 RTU方案简介: 远程终端单元( Remote Terminal Unit,RTU),一种针对通信距离较长和工业现场环境恶劣而设计的具有模块化结构的、特殊的计算机测控单元,它将末端检测仪表和执行机构与远程控制中心相连接。 奇迹TCP RTUGNS…

OpenHarmony(鸿蒙南向)——平台驱动指南【PWM】

往期知识点记录: 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~ 持续更新中…… 概述 功能简介 PWM即脉冲宽度调制(Pulse Width Modul…

Flutter中使用FFI的方式链接C/C++的so库(harmonyos)

Flutter中使用FFI的方式链接C/C库(harmonyos) FFI plugin创建和so的配置FFI插件对so库的使用 FFI plugin创建和so的配置 首先我们可以根据下面的链接生成FFI plugin插件:开发FFI plugin插件 然后在主项目中pubspec.yaml 添加插件的依赖路径&…

排序--堆排序【图文详解】

二叉树的相关概念 叶子:没有子节点的节点叫叶子节点 大根堆:所有的父亲大于儿子 小根堆:所有的儿子大于父亲 父亲于儿子的的下标关系: 父亲的下标为i ,那么左孩子的下标为2*i1,右孩子的下标为2i2 子的下…

智源研究院与百度达成战略合作 共建AI产研协同生态

2024年9月24日,北京智源人工智能研究院(简称“智源研究院”)与北京百度网讯科技有限公司(简称“百度”)正式签署战略合作协议,双方将充分发挥互补优势,在大模型等领域展开深度合作,共…

tomcat服务搭建部署ujcms网站

tomcat服务搭建部署ujcms网站 关闭selinux和防火墙 setenforce 0 && systemctl stop firewalld安装java环境 #卸载原有java8环境 yum remove java*#上传java软件包,并解压缩 tar -xf openjdk-11.0.1_linux-x64_bin.tar.gz && mv jdk-11.0.1 jdk11…

Elasticsearch讲解

1.Elasticsearch基本知识 1.基本认识和安装 Elasticsearch是由elastic公司开发的一套搜索引擎技术,它是elastic技术栈中的一部分。完整的技术栈包括: Elasticsearch:用于数据存储、计算和搜索 Logstash/Beats:用于数据收集 Kib…

【学习笔记】地平线J3J5J6E对比

内容J3J5J6ECPU 4核Cortex-A53 1.2GHz 8核Cortex-A55 1.2GHz 6核Cortex-A78AE 1.5GHz MCU/ MStar 双核锁步Cortex-MStar 2核Cortex-R52 One DCLS core pairand one Split-Lock core 1.2GHz GPU// Mail-G78AE 800MHz 100 FP32 GFLOPS BPU 2*Bernoulli-architecture 5TOPS 2…

测试部署单副本 oceanbase-3.2.4.1 企业版

由于项目需要,测试部署单副本 oceanbase-3.2.4.1 企业版 1.安装前提 准备4cpu,12G内存,100G磁盘 统为centos7.9 yum install -y yum-utils wget net-tools tree yum-config-manager --add-repo https://mirrors.aliyun.com/oceanbase/OceanBase.repo 2.创建用…

计算机毕业设计Hadoop+Spark知识图谱体育赛事推荐系统 体育赛事热度预测系统 体育赛事数据分析 体育赛事可视化 体育赛事大数据 大数据毕业设计

《HadoopSpark知识图谱体育赛事推荐系统》开题报告 一、研究背景及意义 随着互联网技术的迅猛发展和大数据时代的到来,体育赛事数据的数量呈爆炸式增长。用户面对海量的体育赛事信息,常常感到信息过载,难以快速找到感兴趣的赛事内容。如何高…

C语言中的一些小知识(三)

一、你了解printf()吗? 你知道下面代码的输出结果吗? int a123; printf("%2d \n",a); printf() 函数是 C 语言中用于格式化输出的标准函数,它允许你将数据以特定的格式输出到标准输出设备(通常是屏幕)。p…

uniapp 知识点

自定义导航 在page.json navigationstyle":"custom"navigateTo传参 页面传参只能onLoad(option)里面拿 px和upx的关系 在750设计图中,1px1upx 路由 navigateBack返回上一页 重定向 其实就是把当前页面干掉了 公共组件和页面共同点 computed,watc…

vue初学随笔

Vue基础 Vue基本概念 Vue是什么 Vue是一个渐进式的JavaScript框架,它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。 渐进式:各个特性可以根据项目需要逐渐引入和…

认知杂谈84《菜鸟的自我修炼:知易行难与行难知易》

内容摘要: 理解与行动之间的差距是日常生活的常见挑战。"知易行难"体现在理解简单但执行困难,例如知道蔬菜有益但难以坚持食用。而"行难知易"则是开始时困难但后来容易的任务,如学习骑自行车。 这种差异源于心理惰性和习…

Oracle RMAN 无敌备份脚本

1 说明 上一篇文章:Oracle逻辑备份脚本,介绍了如何部署Oracle数据库的逻辑备份脚本,在数据迁移场景下十分好用,但是作为备份来说有点牵强。仅仅有逻辑备份时,当故障发生后,逻辑备份恢复只能恢复到某一时刻…

OpenHarmony(鸿蒙南向)——平台驱动指南【MIPI CSI】

往期知识点记录: 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~ 持续更新中…… 概述 功能简介 CSI(Camera Serial Interface&#xf…

JavaScript 学习

一、输出 为方便调试可以输出内容&#xff0c;但是用户是看不到的。要在开发者模式中看。 console . log ( "Hello" )&#xff1b; 二、外部文件引用 可以直接在html中写JS <head> <meta charset"utf-8"> <script> console.log("he…