[Java 源码] 美团一面~ArrayList 的底层实现

文章目录

      • 1. ArrayList 与 数组的区别
      • 2 ArrayList 的初始化容量
      • 3. ArrayList 的扩容具体指什么
      • 4. ArrayList是如何实现扩容的?
      • 5. ArrayList有缩容吗?

1. ArrayList 与 数组的区别

ArrayList 的底层是数组队列,相当于动态数组。与 Java 中的数组相比,它的容量能动态增长。在添加大量元素前,应用程序可以使用ensureCapacity操作来增加 ArrayList 实例的容量。这可以减少递增式再分配的数量。

2 ArrayList 的初始化容量

// 默认容量是10
private static final int DEFAULT_CAPACITY = 10;
// 如果容量为0的时候,就返回这个数组
private static final Object[] EMPTY_ELEMENTDATA = {};
// 使用默认容量10时,返回这个数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// 元素存放的数组
transient Object[] elementData;
// 元素的个数
private int size;// 记录被修改的次数
protected transient int modCount = 0;
// 数组的最大值
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8

ArrayList有三个构造方法,不同的构造方法的容量是不一样的,具体可以查看JDK 源码。
● 如果不传入初始容量,就使用默认容量,并设置 elementData为DEFAULTCAPACITY_EMPTY_ELEMENTDATA
● 如果传入初始容量,会判断这个传入的值,如果大于0,就 new一个新的Object数组,如果等于0,就直接设置 elementData为 EMPTY_ELEMENTDATA。
● 如果传入一个 Collection,则会调用toArray()方法把它变成一个数组并赋值给elementData。同样会判断它的长度是否为0,如果为0,设置elementData为EMPTY_ELEMENTDATA。

3. ArrayList 的扩容具体指什么

ArrayList里面有两个概念,一个是capacity,它表示的就是“容量”,其实质是数组elementData的长度。而size则表示的“存放的元素的个数”。
因为 Java 中,数组操作不能越界,所以我们必须要保证在插入操作的时候,不会抛出数组越界异常。

4. ArrayList是如何实现扩容的?

扩容主要分两种,自动扩容和手动扩容。
自动扩容底层主要是三个私有方法:


// 扩容一个
private Object[] grow() {return grow(size + 1);
}// 保证扩容到期望容量minCapacity及以上
private Object[] grow(int minCapacity) {return elementData = Arrays.copyOf(elementData,newCapacity(minCapacity));
}// 根据期望容量minCapacity计算实际需要扩容的容量
private int newCapacity(int minCapacity) {// overflow-conscious codeint oldCapacity = elementData.length; // 得到旧容量int newCapacity = oldCapacity + (oldCapacity >> 1); // 设置新容量为旧容量的1.5倍if (newCapacity - minCapacity <= 0) { // 如果新容量仍然小于期望容量if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) // 如果是使用的默认容量return Math.max(DEFAULT_CAPACITY, minCapacity); // 取默认容量和期望容量较大值返回if (minCapacity < 0) // overflow // 检查期望容量是否越界(int 的范围)throw new OutOfMemoryError();return minCapacity; // 返回期望容量}// 如果新容量大于期望容量,判断一下新容量是否越界return (newCapacity - MAX_ARRAY_SIZE <= 0)? newCapacity: hugeCapacity(minCapacity);
}

可以看到,底层其实是调用了Arrays.copyOf方法来进行扩充数组容量的。这里我们主要看一下最后一个方法newCapacity(int minCapacity)的实现。

默认情况下,新的容量会是原容量的1.5倍,这里用了位运算提高效率。一般情况下,如果扩容1.5倍后就大于期望容量,那就返回这个1.5倍旧容量的值。而如果小于期望容量,那就返回期望容量。这里对默认容量10做了特殊处理。
使用1.5倍这个数值而不是直接使用期望容量,是为了防止频繁扩容影响性能。试想如果每次add操作都要扩容一次,那性能将会非常低下。

手动扩容主要是一个公有方法ensureCapacity:

public void ensureCapacity(int minCapacity) {if (minCapacity > elementData.length&& !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA&& minCapacity <= DEFAULT_CAPACITY)) {modCount++;grow(minCapacity);}
}

5. ArrayList有缩容吗?

ArrayList没有缩容。无论是remove方法还是clear方法,它们都不会改变现有数组elementData的长度。但是它们都会把相应位置的元素设置为null,以便垃圾收集器回收掉不使用的元素,节省内存。

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

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

相关文章

2023年【P气瓶充装】找解析及P气瓶充装复审模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 P气瓶充装找解析参考答案及P气瓶充装考试试题解析是安全生产模拟考试一点通题库老师及P气瓶充装操作证已考过的学员汇总&#xff0c;相对有效帮助P气瓶充装复审模拟考试学员顺利通过考试。 1、【多选题】CNG双燃料汽车…

Dockerfile 与 Docker Compose区别

目录 Dockerfile Docker Compose 综合比较 Dockerfile 用途&#xff1a; Dockerfile 用于定义单个容器的构建过程。它包含了一系列指令&#xff0c;每个指令都代表容器构建过程中的一个步骤。这些步骤包括从基础镜像中构建、安装依赖、拷贝文件、设置环境变量等操作。 语法…

【IEEE独立出版】2024第四届神经网络、信息与通信工程国际学术会议(NNICE 2024)

2024第四届神经网络、信息与通信工程国际学术会议&#xff08;NNICE 2024&#xff09; 2024 4th International Conference on Neural Networks, Information and Communication Engineering 2024第四神经网络、信息与通信工程国际学术会议&#xff08;NNICE 2024&#xff0…

电商API接口对于实现电商系统平台的搭建有哪些作用?

电商API接口用于实现电商平台的数据交互和功能调用。具体来说&#xff0c;电商API接口可以用于以下几个方面&#xff1a; 1. 商品管理&#xff1a;通过API接口&#xff0c;可以实现商品的添加、修改、删除、查询等操作。商家可以通过API接口将自己的商品信息上传到电商平台&…

三、Linux高级命令

目录 1、重定向命令 1.1 重定向 > 1.2 重定向 >> 该章节的所有操作都在/export/data/shell目录进行&#xff0c;请提前创建该目录。 mkdir -p /export/data/ 1、重定向命令 1.1 重定向 > Linux 允许将命令执行结果重定向到一个文件&#xff0c;本应显示在…

群晖NAS:docker(Container Manager)、npm安装Verdaccio并常见命令集合

群晖NAS&#xff1a;docker&#xff08;Container Manager&#xff09;、npm安装Verdaccio并常见命令集合 自建 npm 资源库&#xff0c;使用Verdaccio。如果觉得麻烦&#xff0c;直接可以在外网注册 https://www.npmjs.com/ 网站。大同小异&#xff0c;自己搭建搭建方便局域网…

虾皮、Lazada稳定的测评系统需要哪些技术要求

测评作为一项高效运营手段&#xff0c;具有显著的重要性。然而&#xff0c;对于卖家而言&#xff0c;自行建立一套测评系统所需的技术条件并非易事。 在构建系统之前&#xff0c;必须深入理解每个平台的控制风险机制&#xff0c;而后才能开展下一步的建设工作。 1.首先&#…

代币化:2024年的金融浪潮预示着什么?

自“TradFi”领袖到加密专家&#xff0c;各方预测代币化机会高达数十万亿。虽然已有引人注目的用例&#xff0c;但与未来几年可能在链上转移的大量数字化资产相比&#xff0c;这些仅是冰山一角。 代币化何时会变为洪流&#xff1f;什么阻碍了其发展&#xff1f; 今年10月&…

SpringBoot下使用Quartz设置定时任务

SpringBoot下使用Quartz设置定时任务 基础使用添加依赖demo 基础使用 Quartz 的核心类有以下三部分&#xff1a; 任务 Job &#xff1a; 需要实现的任务类&#xff0c;实现 execute() 方法&#xff0c;执行后完成任务。触发器 Trigger &#xff1a; 包括 SimpleTrigger 和 Cr…

VGN S99快捷键,说明书

VGN S99快捷键-说明书 按键说明灯光效果常见疑难 按键说明 切换关闭电量指示灯&#xff1a;Fn home 灯光效果 常见疑难

服务器,数据库服务器各指标怎么看?

一&#xff09;服务器&#xff1a; 1&#xff09; 系统负载 load 1m,load 5m,load 15m分别是什么意思&#xff1f; 1m 表示过去 1 分钟的平均负载&#xff0c;5m 表示过去 5 分钟的平均负载&#xff0c;15m 表示过去 15 分钟的平均负载。系统负载是指系统在过去一段时间内处理的…

GPT5大剧第二季开启,Sam Altman 重掌 OpenAI CEO 大权

OpenAl 最新公告: Sam Altman 重掌 OpenAI CEO 大权&#xff0c;公司迎来新的初始董事会 Mira Murati 出任 CTO,Greg Brockman 再次成为总裁。来看看CEO Sam Altman和董事会主席 Bret Taylor的最新发言。 2023年11月29日 以下是 CEO Sam Altman和董事会主席 Bret Taylor 今天下…

在Docker上部署Springboot项目

在Docker上部署Springboot项目 ###1.安装docker 2.安装mysql 拉 Mysql 镜像 docker pull mysql:5.7.31运行 Mysql 5.7.31 第一次运行需要设置密码 docker run -d --name myMysql -p 9506:3306 -v /data/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD1234 mysql:5.7.31不是…

微服务API网关Spring Cloud Gateway实战

概述 微服务网关是为了给不同的微服务提供统一的前置功能&#xff1b;网关服务可以配置集群&#xff0c;以承载更多的流量&#xff1b;负载均衡与网关互相成就&#xff0c;一般使用负载均衡&#xff08;例如 nginx&#xff09;作为总入口&#xff0c;然后将流量分发到多个网关…

mybatis参数输入 #{}和${}

1、建库建表 CREATE DATABASE mybatis-example;USE mybatis-example;CREATE TABLE t_emp(emp_id INT AUTO_INCREMENT,emp_name CHAR(100),emp_salary DOUBLE(10,5),PRIMARY KEY(emp_id) );INSERT INTO t_emp(emp_name,emp_salary) VALUES("tom",200.33); INSERT INTO…

【测试】C/S结构与B/S结构的概念与区别

随心所欲而无愧于心 文章目录 前言1. B/S1.1 B/S结构概念1.2 B/S结构软件的工作过程1.3 B/S结构软件的环境搭建 2. C/S结构软件2.1 C/S结构概念2.2 C/S软件工作过程 前言 一般情况下&#xff0c;软件有两种结构架构&#xff0c;一种是浏览器/服务器即B/S&#xff08;Browser/S…

Unity中Shader编译目标渲染器

文章目录 前言一、Unity在打包时&#xff0c;会把Shader编译成不同平台对应的代码我们在状态栏&#xff0c;可以看见我们目前所处于的目标平台 二、在Unity中&#xff0c;怎么指定目标平台1、#pragma only_renderers2、#pragma exclude_renderers 三、我们测试一下看看效果1、 …

C语言重点突破(六)文件操作

本章重点 1. 为什么使用文件 2. 什么是文件 3. 文件的打开和关闭 4. 文件的顺序读写 5. 文件的随机读写 6. 文本文件和二进制文件 7. 文件读取结束的判定 8. 文件缓冲区 1. 为什么使用文件 我们在前面的文章介绍了通讯录的程序&#xff0c;当通讯录运行起来的时候&#xff0c…

Mysql深入——7

count&#xff08;*&#xff09;为什么这么慢&#xff1f;&#xff1f;&#xff1f; 在不同的MySQL引擎中&#xff0c;count&#xff08;*&#xff09;有不同的实现方式&#xff0c;MyISAM引擎将一个表的总行存在了磁盘上&#xff0c;需要的时候会直接返回&#xff0c;但InnoD…

ubuntu终端代理配置

ubuntu浏览器的无需手动设置,主要解决在终端中的配置问题,按照下面配置后可能会ping不通一些ip,但wget/git都是可以的,具体原因以后再分析 查找端口 首先要找到自己代理对应的HTTP端口,以QV2ray软件作为示例,我为8889 手动配置 # 配置系统proxy export http_proxy=1…