当前位置: 首页 > news >正文

Java集合源码解析之ArrayList

目录

1.ArrayList源码解析

整体流程图概览

构造方法

无参构造方法

有参构造方法

add()

重点子方法grow(xxx)

2.LinkedList 源码解析

3.HashMap源码解析****※


1.ArrayList源码解析

整体流程图概览

构造方法

        arrayList的构造方法就做一件事情,就是初始化一下储存数据的容器,其实本质上就是一个数组,在其中就叫elementData

无参构造方法

/*** 构造一个空容量的数组(DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {})*/public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}

有参构造方法

   /*** Constructs an empty list with the specified initial capacity.** @param initialCapacity the initial capacity of the list* @throws IllegalArgumentException if the specified initial capacity*                                  is negative*/public ArrayList(int initialCapacity) {if (initialCapacity > 0) {this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {this.elementData = EMPTY_ELEMENTDATA;// /将自定义的容量大小当成初始化elementData的大小} else {throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);}}

add()

/*** 新增元素操作,执行如下操作:*      List list = new ArrayList();*      list.add("a1");*/// eg1:第一次新增元素e="a1"public boolean add(E e) {/** 确定是否需要扩容,如果需要,则进行扩容操作*/ensureCapacityInternal(size + 1); // eg1:size=0// eg1:size=0,elementData[0]="a1",然后a自增为1elementData[size++] = e;return true;}// eg1:第一次新增元素,size=0,则:minCapacity=size+1=0+1=1private void ensureCapacityInternal(int minCapacity) {// eg1:第一次新增元素,calculateCapacity方法返回值为DEFAULT_CAPACITY=10ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));}/*** 计算ArrayList的容量,如果elementData数组中没有已存储的元素,则返回默认值10,否则,返回minCapacity。*/// eg1:第一次新增元素,elementData={} minCapacity=1private static int calculateCapacity(Object[] elementData, int minCapacity) {if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) // DEFAULTCAPACITY_EMPTY_ELEMENTDATA={}return Math.max(DEFAULT_CAPACITY, minCapacity); // eg1:return 10return minCapacity;}/*** 确保明确的ArrayList的容量*/// eg1:minCapacity=10private void ensureExplicitCapacity(int minCapacity) {/** 变化次数加1 */modCount++; // eg1: modCount++后,modCount=1/** 如果所需的【最小容量】大于elementData数组的容量,则进行扩容操作 */if (minCapacity - elementData.length > 0)  // eg1:elementData.length=0grow(minCapacity); // eg1:minCapacity=10}

重点子方法grow(xxx)

grow(xxx); arrayList核心的方法,能扩展数组大小的真正秘密

/*** 增加容量以确保它至少可以容纳最小容量参数指定的元素数量。*/// eg1:minCapacity=10private void grow(int minCapacity) {/** 原有数组elementData的长度 */int oldCapacity = elementData.length; // eg1:oldCapacity=0/*** A >> 1 等于 A/2* eg: 3 >> 1 = 3/2 = 1*     4 >> 1 = 4/2 = 2* ------------------------* A << 1 等于 A*2* eg: 3 << 1 = 3*2 = 6*     4 << 1 = 4*2 = 8** 000100 >> 1 = 000010* 000100 << 1 = 001000*//** 新增oldCapacity的一半整数长度作为newCapacity的额外增长长度 */int newCapacity = oldCapacity + (oldCapacity >> 1); // eg1:newCapacity=0+(0>>1)=0/** 新的长度newCapacity依然无法满足需要的最小扩容量minCapacity,则新的扩容长度为minCapacity */if (newCapacity - minCapacity < 0) // eg1:truenewCapacity = minCapacity; // eg1:newCapacity=10/** 新的扩容长度newCapacity超出了最大的数组长度MAX_ARRAY_SIZE(huge:巨大的) */if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);/** 扩展数组长度为newCapacity,并且将旧数组中的元素赋值到新的数组中 */elementData = Arrays.copyOf(elementData, newCapacity); // eg1:newCapacity=10, 扩容elementData的length=10}private static int hugeCapacity(int minCapacity) {if (minCapacity < 0) { // overflowthrow new OutOfMemoryError();}return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;}

        正常情况下会扩容1.5倍,特殊情况下(新扩展数组大小已经达到了最大值)则只取最大值。当我们调用add方法时,实际上的函数调用如下:

                                                     

 

重点总结 


1)arrayList可以存放null。
2)arrayList本质上就是一个elementData数组。
3)arrayList区别于数组的地方在于能够自动扩展大小,其中关键的方法就是gorw()方法。
4)arrayList中removeAll(collection c)和clear()的区别就是removeAll可以删除批量指定的元素,而clear是全是删除集合中的元素。
5)arrayList由于本质是数组,所以它在数据的查询方面会很快,而在插入删除这些方面,性能下降很多,有移动很多数据才能达到应有的效果
6)arrayList实现了RandomAccess,所以在遍历它的时候推荐使用for循环。

部分参考:ArrayList源码解析-CSDN博客     

 

2.LinkedList 源码解析

Java集合源码解析之LinkedList-CSDN博客

3.HashMap源码解析****※

点击下方链接获取

HashMap源码解析

http://www.dtcms.com/a/363005.html

相关文章:

  • DELPHI 利用OpenSSL实现加解密,证书(X.509)等功能
  • PFLOTRAN 模拟多相、多组分、反应性流动与传输过程的高性能并行数值模拟软件
  • spring boot驴友结伴游网站的设计与实现(代码+数据库+LW)
  • 深入分析 json2(新)与标准的 jsonrpc的区别
  • Maven + JUnit:Java单元测试的坚实组合
  • Qt6实现绘图工具:12种绘图工具全家桶!这个项目满足全部2D场景
  • 机器学习 - Kaggle项目实践(7)NLP with Disaster Tweets 灾难消息
  • WPF迁移avalonia之图像处理(一)
  • STM32HAL 快速入门(十六):UART 协议 —— 异步串行通信的底层逻辑
  • 网络编程 socket——TCP
  • (CVPR-2024)VideoBooth:基于扩散的视频生成与图像提示
  • HTML5 简介和基础骨架
  • Linux 入门到精通,真的不用背命令!零基础小白靠「场景化学习法」,3 个月拿下运维 offer,第二十四天
  • 在 Qt 的 .pro 文件中设置警告级别和 C++11 标准
  • .NET技术深度解析:现代企业级开发指南
  • PCB传输线的拓扑结构
  • 启动 Springboot 方式不同,导致无法读取中文文件名的文件
  • 基于单片机颜色识别分拣系统设计
  • 一款为开发者而生的开源全栈LLMOps平台
  • 面试官常问:Redis 为什么快?这篇回答满分!
  • SRE团队是干嘛的
  • 前端环境安装
  • 【Redis】 常用数据结构之String篇:从SET/GET到INCR的超全教程
  • Jetson Thor平台JP7.0版本96712 GMSL相机驱动调试记录
  • 科技信息差(9.2)
  • 企业级按钮弹层组件封装思路
  • 第四章 windows实战-emlog
  • 关于嵌入式学习——嵌入式硬件1
  • 【JavaScript】读取商品页面中的结构化数据(JSON-LD),在不改动服务端情况下,实现一对一跳转
  • 不只是一台玩具车:开源燃料电池机器人HydroBot全揭秘