ArrayList如何深究?最简单的数组~

目录

数组 Array

为什么数组索引从0开始呢?为什么不从1开始?

ArrayList

成员变量

构造方法

添加和扩容

ArrayList底层的实现原理是什么?

数组和List转换

ArrayList 和 LinkedList区别

底层数据结构

操作数据效率

内存占用

线程安全


数组 Array

数组(Array)是一种用连续的内存空间存储相同数据类型数据的线性数据结构。

寻址公式:a[i] = baseAddress + i * dataTypeSize

假定要想访问int数组中的第3个元素(索引为2),也就是数组的首地址加上2×4字节,所以最终访问到的就是18的位置,也就是第3个元素,索引值为2,数据空间为88。

为什么数组索引从0开始呢?为什么不从1开始?

假设数组索引从1开始,寻址公式就变成了:a[i] = baseAddress + (i-1) * dataTypeSize

根据数组索引获取元素的时候,会用索引和寻址公式来计算内存所对应的数据,寻址公式是数组的首地址+索引乘以存储数据的类型大小(如int就是4字节)

如果索引从1开始,寻址公式中就需要增加一次减法操作,对于cpu来说性能就会下降。

ArrayList

成员变量

在ArrayList中,默认的初始容量就是DEFAULT_CAPACITY = 10。

构造方法

ArrayList有三个构造方法,并且根据不同的传入参数构成了重载。

分别是带初始化容量的构造函数、无参构造函数和传入一个collection。当传入一个collection时,会把这个对象通过toArray方法转成数组,然后将数组的地址赋给elementData。

比如ArrayList list = new ArrayList(10)中这个list其实没有扩容,在初始化的时候传入一个10作为参数,ArrayList会直接初始化一个大小为10的数组。

添加和扩容

当ArrayList第一次添加数据,会先初始化再调用add方法:

进入到add方法,会先确保内部容量为size+1,size初始化是0:

进入ensureCapacityInternal,确保内部容量:

进入calculateCapacity,此时if条件中,DEFAULT_CAPACITY初始化为10,所以会返回10:

再进入ecsureExplicitCapacity,if,如果这个判断大于0,说明容量不够需要扩容:

此时会进入到grow中进行扩容,通过不同的if来判断,先进行容量增加,

oldCapacit + (oldCapacit >> 1),也就是扩容为原来容量的1.5倍。

初始化数组后,再进行数组拷贝。

ArrayList底层的实现原理是什么?

ArrayList底层是用动态数组来实现的,初始容量为0,当第一次添加元素的时候才会初始化容量为10。ArrayList在进行扩容的时候,会扩大为原来的1,5倍,每次扩容都需要拷贝数组。

在add一个数据的时候,会先判断当前数组使用长度(size)加1后足够存下这个数据,这个判断会先计算数据的容量,如果当前数组已使用长度+1后大于当前数组长度,就会调用grow方法进行扩容。确保新增的数据有地方存储之后,会将新的元素添加到size的位置上。

数组和List转换

数组转List:Arrays.asList,也就是使用Arrays工具类的asList方法。

修改数组内容,list会受影响,因为asList方法本质上只是使用Arrays类中的一个内部类ArrayList来构造集合,最终指向的都是同一个内存地址。

List转数组:list.toArray,也就是使用List的toArray方法。

修改数组内容,list不会受影响,toArray底层进行了数组的拷贝,内存地址不同,所以不受影响。

ArrayList 和 LinkedList区别

底层数据结构

ArrayList基于动态数组、LinkedList基于双向链表。

操作数据效率

ArrayList按照索引查询很快,是O(1),ArrayList和LinkedList查找某一元素都需要遍历,O(n)。

ArrayList插入和删除需要改变大量元素位置,平均复杂度为O(n),LinkedList需要遍历链表,平均复杂度为O(n)。

内存占用

ArrayList底层是数组,在内存中连续,节省内存;LinkedList双向链表需要多两个指针,更占内存。

线程安全

都不是线程安全的,要保证线程安全可以使用Collection.synchronizedList。

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

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

相关文章

前端开发入门指南Day 14 :数据交互(从Ajax到Axios)和工具进阶(JSON、代理、正则表达式)

今天,我们将探索前端开发中最重要的几个实用工具和概念。这些工具就像是前端开发者的瑞士军刀,帮助我们更好地处理数据和实现各种功能。 一、HTTP请求:前后端通信的桥梁 🌉 为什么需要HTTP请求? 想象你在餐厅点餐&a…

三十一:HTTP多种重定向跳转方式的差异

在现代网站开发中,HTTP 重定向是一种常见的技术,用于将用户的请求从一个 URL 跳转到另一个 URL。重定向机制广泛应用于网站迁移、SEO 优化、以及内容管理系统中。不同的 HTTP 状态码代表不同的重定向方式,每种方式的行为和适用场景各有不同。本文将深入探讨 HTTP 重定向的几…

C++ 分治

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 1.分治法 2.二分搜索 函数传参——数组 3.棋盘覆盖 4.合并排序 5.快速排序 提示:以下是本篇文章正文内容,下面案例可供参考 1.分治法 基…

anaconda环境下安装第三方库

在 Anaconda 环境中使用 pip install 安装某些包时,可能会出现依赖或环境相关的问题。针对 fastdtw 的安装问题,你可以尝试以下解决方案: 1. 使用 Conda 安装 fastdtw Anaconda 的 conda 包管理器可以更好地处理依赖问题,尤其是…

用函数实现模块化程序设计(七)--数组作为函数参数(排序算法)

调用有参函数时,需要实参,实参可以是常量,变量,表达式,数组元素的作用与变量相当,凡是变量出现的地方都可用数组代替,数组元素可以用作函数实参,数组名可以作实参和形参,…

嵌入式Linux无窗口系统下搭建 Qt 开发环境

嵌入式Linux无窗口系统下搭建 Qt 开发环境 本文将介绍如何在树莓派的嵌入式 Linux 环境下,搭建 Qt 开发环境,实现无窗口系统模式(framebuffer)下的图形程序开发。 1. 安装 Qt 环境 接下来,安装核心 Qt 开发库以及与 …

基于STM32设计的智能宠物喂养系统(华为云IOT)_273

文章目录 一、前言1.1 项目介绍【1】项目开发背景【2】设计实现的功能【3】项目硬件模块组成【4】设计意义【5】国内外研究现状【6】摘要1.2 设计思路1.3 系统功能总结1.4 开发工具的选择【1】设备端开发【2】上位机开发1.5 参考文献1.6 系统框架图1.7 系统原理图1.8 实物图1.9…

C++【PCL】利用矩阵对点云进行刚体变换

/** 功能&#xff1a; 点云刚体变换* 头文件&#xff1a; #include <pcl/common/transforms.h>* 功能函数&#xff1a; pcl::transformPointCloud(*pPointCloudIn, *pPointCloudOut, transform_1);*/#include <pcl/io/ply_io.h>#include <iostream>// pcl #i…

Java项目实战II基于微信小程序的文章管理系统的设计与实现 (开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、核心代码 五、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 一、前言 在信息爆炸的时代&#xff0c;内容创作与管理已成为众…

Conda 管理python开发环境

同步发布于我的网站 &#x1f680; 故事起因: 在公司使用Requests多任务并行开发时遇到了问题&#xff0c;使用 ProcessPoolExecutor 时不能正常发出网络请求&#xff0c;会卡在网络请求发不出去&#xff0c;但是善于用 ThreadPoolExecutor 时是可以的,纠结了很久&#xff0c;一…

【学习Go编程】

了解Go语言的基本概念&#xff1a; 学习Go的基本语法、数据类型、控制结构等。可以参考官方文档或基础教程来入门。 安装Go环境&#xff1a; 访问Go语言的官方网站&#xff0c;下载并安装适合你操作系统的Go编程环境。配置好环境变量&#xff0c;确保可以在命令行中使用go命令…

LLaMA-Factory 上手即用教程

LLaMA-Factory 是一个高效的大型语言模型微调工具&#xff0c;支持多种模型和训练方法&#xff0c;包括预训练、监督微调、强化学习等&#xff0c;同时提供量化技术和实验监控&#xff0c;旨在提高训练速度和模型性能。 官方开源地址&#xff1a;https://github.com/hiyouga/L…

PGSQL:联合唯一索引的创建和删除

创建联合唯一索引 假设有一个表 your_table&#xff0c;它有多个列&#xff0c;你想在其中的几列上创建一个联合唯一索引。以下是创建联合唯一索引的 SQL 语句&#xff1a; CREATE UNIQUE INDEX idx_unique_columns ON your_table(column1, column2, ...);注意&#xff1a; …

抓包之查看websocket内容

写在前面 本文看下websocket抓包相关内容。 1&#xff1a;正文 websocket基础环境搭建参考这篇文章。 启动后&#xff0c;先看chrome的network抓包&#xff0c;这里我们直接使用is:running来过滤出websocket的请求&#xff1a; 可以清晰的看到发送的内容以及响应的内容。在…

项目介绍和游戏搭建(拼图小游戏)

1. &#xff08;1&#xff09; import javax.swing.*;public class GameJFrame extends JFrame {//游戏主界面&#xff0c;游戏的所有逻辑public GameJFrame(){this.setSize(603,680);this.setVisible(true);//true是展示&#xff0c;flase是隐藏} } &#xff08;2&#xff…

Flask项目入门—会话技术Cookie和Session

Session和Cookie都是用于跟踪用户会话的技术、它们可以存储用户信息&#xff0c;以便在用户与网站进行交互时提供个性化的体验。然而&#xff0c;这两者在存储位置、使用方式、安全性等方面存在显著的差异。 工作原理/流程 Cookie 1、用户第一次访问时候服务器生成 Cookie&a…

【Maven】Nexus私服

6. Maven的私服 6.1 什么是私服 Maven 私服是一种特殊的远程仓库&#xff0c;它是架设在局域网内的仓库服务&#xff0c;用来代理位于外部的远程仓库&#xff08;中央仓库、其他远程公共仓库&#xff09;。一些无法从外部仓库下载到的构件&#xff0c;如项目组其他人员开发的…

前端Web性能分析工具扫盲

对于前端大型项目来说,很容易产生性能问题。对于这些性能问题,最常见的解决方式是使用性能分析工具进行分析,然后再进行针对性的解决。 一、Chrome DevTools 一般来说,前端的性能分析通常可以从时间和空间两个角度来进行: 时间:常见耗时,如页面加载耗时、渲染耗时、网…

一键生成后端服务,MemFire Cloud重新定义开发效率

作为开发者&#xff0c;特别是独立开发者和小团队成员&#xff0c;大家都知道开发的最大难题之一就是搭建后端服务。要让一个应用从零开始&#xff0c;除了前端的开发工作外&#xff0c;还需要考虑数据库、接口、认证、存储等等一系列繁琐的后台工作。而MemFire Cloud这款神器&…

HarmonyOS(60)性能优化之状态管理最佳实践

状态管理最佳实践 1、避免在循环中访问状态变量1.1 反例1.2 正例 2、避免不必要的状态变量的使用3、建议使用临时变量替换状态变量3.1 反例3.2 正例 4、参考资料 1、避免在循环中访问状态变量 在应用开发中&#xff0c;应避免在循环逻辑中频繁读取状态变量&#xff0c;而是应该…