【Java容器(jdk17)】ArrayList深入源码,就是这么简单
ArrayList深入源码
- 一、ArrayList源码解析
- 1. MIXIN 的混入
- 2. 属性说明
- 3. 构造方法
- 4. 其他方法(核心)
- iterator 和 listIterator 方法
- add方法
- remove 方法
- sort方法
- 其他
- 二、ArrayList 为什么是线程不安全的?体现哪些方面呢?
- 三、ArrayList 细节汇总
前言:
个人觉得看源代码会增进不少知识,一直都是看别人写的博客中的代码片段,没自己静下心来去看过,接下来体验体验源码的快乐。
一、ArrayList源码解析
对 ArrayList 相应关系有了大致的了解后,咱由外到里依次深入。
1. MIXIN 的混入
ArrayList 利用 MIXIN 的思想,实现了多继承。
说明其实现的接口:
Serializable
接口:使得ArrayList 支持序列化和反序列化。RandomAccess
接口:该接口是一个标记接口,意在标明ArrayList 具备快速随机访问的能力,使用for 会比使用 迭代器(iterator)访问速度要快。LinkedList 那边即不具备这种能力,所以不存在这种标记(原因是因为LinkedList 底层是链表,访问都是从根到尾的,所以它使用迭代器会更快)。Cloneable
接口:也是一个标记接口,实现了它便可以去重写Object 下的clone 方法,利于对象进行创建副本。(注意:是ArrayList 实现了Cloneable接口,当利用多态向上转型为List 时,是不可以使用的。)
下面是 ArrayList 内部重写的 clone 方法的代码。
/*** Returns a shallow copy of this {@code ArrayList} instance. (The* elements themselves are not copied.)** @return a clone of this {@code ArrayList} instance*/public Object clone() {try {ArrayList<?> v = (ArrayList<?>) super.clone();v.elementData = Arrays.copyOf(elementData, size);v.modCount = 0;return v;} catch (CloneNotSupportedException e) {// this shouldn't happen, since we are Cloneablethrow new InternalError(e);}}
emmmm…这里我不知道返回值的数据类型不直接为 ArrayList
,一般我去重写的话就会直接。。。
2. 属性说明
3. 构造方法
ArrayList 有三个构造方法,俩有参,一无参的。
第三个描述的那个构造方法如何使用呢 ?
由于Arrays.asList()
得到的集合固定大小的,是由Arrays内部类所实例化的,是没有 clone(),add(),remove(),clear()
等这样的动态操作的,但如果想要使用这种动态操作怎么办呢?
那咱就可以利用这个构造方法,看代码更清晰:
String[] s = {"xx","yy"};//List<String> xxx = Arrays.asList(s);//xxx.add("mm"); /*这里运行最后是会报异常的,这是因为Arrays 里面有个ArrayList 的内部类,它没有重写add和remove等方法。但没运行是不会爆红的,虽然没有重写那些方法,但该内部类继承了AbstractList,这个类里面这些方法不是抽象的...*/List<String> list = new ArrayList<>(Arrays.asList(s));list.add("mm");list.forEach(System.out::println);// 正常输出
4. 其他方法(核心)
先不说方法,先说说类里面实现的Iterator
接口和它的子接口,ListIterator
接口。(虽然ArrayList 实例对象用迭代器的话比较少,但是量变质不变,LinkedList 可以用啊)。
iterator 和 listIterator 方法
- 看看Iterator 接口的实现类
Itr
内部吧:
- 再来看看
ListIterator
接口实现类ListItr
(继承了Itr
) 的内部吧:
这里继承,所以forEachRemaining
方法也是可以使用的。
有了 listIterator()
, 不会还有人用 iterator()
吧。注意ListIterator 只在List 集合中出现了哦,也就是 Vector、ArrayList、LinkedList、Stack这样的。
也可以看看 JAVA中ListIterator和Iterator详解与辨析 这篇博客对其的一些解释。
add方法
add 对外提供的方法有俩,
add(E e)
和add(int index, E e)
。它俩有公共的点是,判断类内定义的elementData
数组长度是否和元素size(个数)
相匹配,是否需要扩容。
也就是说它们俩有一个共同的方法,让elementData
扩容。咋括滴勒,咱来看看这个grow
方法内部。
咱看别人博客都说是1.5倍扩容的,但是是怎么个扩容呢?下面看源码分析分析。
通过调用 ArraysSupport
类中的newLength
方法,我们获得newCapacity
后,通过Arrays.copyOf
完成扩容。
- 先来看看
ArraysSupport
类中的newLength
方法。(1.5倍的由来)
- 再来看看
Arrays.copyOf
方法调用吧:
它内部用的是System.arraycopy
这个方法。这是核心啊,我觉得这也是ArrayList 性能要比较好的关键。这玩意将数据复制给一个副本然后返回给elementData数组。arraycopy 是本地(native)方法。它强在它是浅拷贝,它是直接拷贝所存放的地址,而不是像深拷贝那样重新分配内存。
有关浅拷贝和深拷贝,可以看看这篇《浅拷贝和深拷贝》,或者我写的这篇《clone方法》。
了解完如何扩容之后,再来看看俩方法的具体实现:
- add(E e)
- add(int index,E e)
remove 方法
remove 方法也有两种对外提供,remove(int index),remove(Object obj)
。
它们都是根据索引去调用内部的 fastRemove(Object[] es, int i)
方法去进行移除。也是调用System
下面的arraycopy
方法,然后把那个设置为空(null),让GC
回收。
咱先来看看 fastRemove
方法的实现吧:
- remove(int index)
- remove(Object obj)
有关 mark
标记的使用可以看这篇博客《mark标号》。
从代码可以看出,不管传入的参数是空还是非空,都会对 elementData
进行操作进行删除。
sort方法
从jdk1.8
后,List接口就引入了sort
这个默认方法。
- List 中的 sort 方法:
- ArrayLIst 重写的 sort 方法(重写的原因很简单,ArrayList内部本就是动态数组所构的,用迭代器去重写对元素进行设置纯属是多余):
及其舒适简单。
可以直接用LIst集合中的sort了,其实调用Collections 工具类中的sort 方法,最后还是会回到List 集合中,还不如直接使用呢。
其他
还有一些常用的 方法,比如:
- set(int index,E element)
- isEmpty()
- get(int index)
- indexOf(Object)
- lastIndexOf(Object)
- clear()
- toArray()
- contains()
trimToSize()
还是通过Arrays.copyOf 将数组长度变成和数组元素个数(size)一致,可以减少空间的损失。- …
理解了 ArrayList 的本质,这些方法的实现其实自己想也想的出来。
二、ArrayList 为什么是线程不安全的?体现哪些方面呢?
可以看看这篇博客写的几点线程不安全的情况以及其测试。
《ArrayList为什么线程不安全 线程不安全体现在哪些方面 源码角度分析其具体原因》
三、ArrayList 细节汇总
- ArrayList 是基于动态数组实现的,当进行插入或删除操作的时候,都会进行数组的拷贝复制。
ArrayList
它很多地方是分步进行操作的,**而且内部元素也是可以为 null 的。**它不是线程安全的。ArrayList
删除元素时,只会改变元素的个数(size
),而不会改变容量(elementData.length
),如果想要更改,可以调用trimToSize()
方法,它会给你改成和元素个数一样的值。
相关文章:

【Java容器(jdk17)】ArrayList深入源码,就是这么简单
ArrayList深入源码一、ArrayList源码解析1. MIXIN 的混入2. 属性说明3. 构造方法4. 其他方法(核心)iterator 和 listIterator 方法add方法remove 方法sort方法其他二、ArrayList 为什么是线程不安全的?体现哪些方面呢?三、ArrayLi…...

【Java 面试合集】简述下Java的三个特性 以及项目中的应用
简述下Java的特征 以及项目中的应用 1. 概述 上述截图中就是Java的三大特性,以及特性的实现方案。接下来就每个点展开来说说 2. 封装 满足:隐藏实现细节,公开使用方法 的都可以理解为是封装 而实现封装的有利手段就是权限修饰符了。可以根据…...

git基本概念图示【学习】
基本概念工作区(Working Directory)就是你在电脑里能看到的目录,比如名字为 gafish.github.com 的文件夹就是一个工作区本地版本库(Local Repository)工作区有一个隐藏目录 .git,这个不算工作区,…...

微前端qiankun架构 (基于vue2实现)使用教程
工具使用版本 node --> 16vue/cli --> 5 创建文件 创建文件夹qiankun-test。 使用vue脚手架创建主应用main和子应用dev 主应用 安装 qiankun: yarn add qiankun 或者 npm i qiankun -S 使用qiankun: 在 utils 内创建 微应用文件夹 microApp,在该文件夹…...

记录robosense RS-LIDAR-16使用过程3
一、wireshark抓包保存pcap文件并解析ubuntu18安装wireshark,参考下面csdn教程,官网教程我看的一脸蒙(可能英语太差)https://blog.csdn.net/weixin_46048542/article/details/121730448?spm1001.2101.3001.6650.2&utm_medium…...
【博学谷学习记录】大数据课程-学习第七周总结
Hadoop配置文件修改 Hadoop安装主要就是配置文件的修改,一般在主节点进行修改,完毕后scp下发给其他各个从节点机器 文件中设置的是Hadoop运行时需要的环境变量。JAVA_HOME是必须设置的,即使我们当前的系统中设置了JAVA_HOME,它也…...

154、【动态规划】leetcode ——494. 目标和:回溯法+动态规划(C++版本)
题目描述 原题链接:494. 目标和 解题思路 (1)回溯法 本题的特点是nums中每个元素只能使用一次,分别试探加上nums[index]和减去nums[index],然后递归的遍历下一个元素index 1。 class Solution { public:int res …...
MySQL-窗口函数
窗口函数概念常用窗口函数聚合窗口函数专用窗口函数语法OVER子句window_specwindow_name (命名窗口)partition_clause 分区order_clause 排序frame_clause 范围 (指定窗口大小)使用限制练习准备概念 窗口函数对一组查询执行类似于聚合的操作。然而&#…...

【C++设计模式】学习笔记(1):面向对象设计原则
目录 简介面向对象设计原则(1)依赖倒置原则(DIP)(2)开放封闭原则(OCP)(3)单一职责原则(SRP)(4)Liskov替换原则(LSP)(5)接口隔离原则(ISP)(6)优先使用对象组合,而不是类继承(7)封装变化点(8)针对接口编程,而不是针对实现编程结语简介 Hello! 非常感谢您阅读海…...

[测开篇]设计测试用例的方法如何正确描述Bug
文章目录为什么测试人员要写测试用例?怎样设计测试用例?(总的方面)1.基于需求设计测试用例(总的方面) 2.页面(总的方面) 3.非功能性测试(具体方面) 4.1 等…...
设计模式学习笔记--单例、建造者、适配器、装饰、外观、组合
以下内容根据以下网址及相关视频整理:Android设计模式之单例模式_谬谬清不给我取名字的博客-CSDN博客_android 单例模式 Android设计模式--单例模式的六种实现和单例模式讲解Volatile与Synchronized相关的并发_龙腾腾的博客-CSDN博客_android 单例 volatile java …...
English Learning - Day5 L1考前复习 2023.2.10 周五
English Learning - Day5 L1考前复习 2023.2.10 周五1 单选题:She has the face _________.2 单选题: The goals ________ he fought all his life no longer seemed important to him.3 单选题:Sales director is a position ______ communi…...
C. Prepend and Append
time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Timur initially had a binary string†† s� (possibly of length 00). He performed the following operation several (possibly zero)…...

javassm超市在线配送管理系统
为了解决用户便捷地在网上购物,本文设计和开发了一个超市管理系统。本系统是基于web架构设计,SSM框架 ,使用Mysql数据库管理,综合采用JSP模式来完成系统的相关功能。主要实现了管理员与用户的注册与登陆,个人中心、用户…...
Scratch少儿编程案例-多模式贪吃蛇(无尽和计时)
专栏分享 点击跳转=>Unity3D特效百例点击跳转=>案例项目实战源码点击跳转=>游戏脚本-辅助自动化点击跳转=>Android控件全解手册点击跳转=>Scratch编程案例👉关于作者...

谷歌蜘蛛池怎么搭建?Google蜘蛛池可以帮助谷歌排名吗?
本文主要分享关于谷歌蜘蛛池的搭建疑问,以及Google对谷歌排名的影响到底有多大。 本文由光算创作,有可能会被剽窃和修改,我们佛系对待这种行为吧。 谷歌蜘蛛池怎么搭建? 答案是:需要一个内链外链体系复杂的站群系统…...

Kubernetes集群-部署Java项目
Kubernetes集群-部署Java项目(SSG) k8s部署项目java流程图 第一步 打包制作镜像 打包 java源码: application.properties #在有pom.xml的路径下执行 mvn clean package制作镜像: 将刚才打包后的文件夹传到,装有dock…...
English Learning - Day54 作业打卡 2023.2.8 周三
English Learning - Day54 作业打卡 2023.2.8 周三引言1. 就算你不喜欢喝酒,也请尝一杯吧。2. 便纵有千种风情,更与何人说?——柳永《雨霖铃》 (来,挑战一下古诗词)3. 虽然忙,我也要参加会议。4. 无论发生什么…...
【Unity题】 1.矩阵旋转,欧拉旋转,四元数旋转各自的优缺点。2.StringBuilder和String的区别
1.矩阵旋转,欧拉旋转,四元数旋转各自的优缺点 矩阵旋转,欧拉旋转,四元数旋转是三种不同的旋转表示方法,下面是它们各自的优缺点: 矩阵旋转: 优点: 1.可以方便地实现复合旋转&…...

【C++面试问答】搞清楚深拷贝与浅拷贝的区别
问题 深拷贝和浅拷贝的区别是面试中的常见问题之一,对于不同的编程语言,这个问题的回答可能稍有差别,下面我们就来探索一下它们之间的异同吧。 先来看看在JavaScript对象的深拷贝与浅拷贝的区别: 浅拷贝:只是复制了…...

高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...

无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...

DBLP数据库是什么?
DBLP(Digital Bibliography & Library Project)Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高,数据库文献更新速度很快,很好地反映了国际计算机科学学术研…...

【堆垛策略】设计方法
堆垛策略的设计是积木堆叠系统的核心,直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法,涵盖基础规则、优化算法和容错机制: 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则: 大尺寸/重量积木在下…...
加密通信 + 行为分析:运营商行业安全防御体系重构
在数字经济蓬勃发展的时代,运营商作为信息通信网络的核心枢纽,承载着海量用户数据与关键业务传输,其安全防御体系的可靠性直接关乎国家安全、社会稳定与企业发展。随着网络攻击手段的不断升级,传统安全防护体系逐渐暴露出局限性&a…...
React核心概念:State是什么?如何用useState管理组件自己的数据?
系列回顾: 在上一篇《React入门第一步》中,我们已经成功创建并运行了第一个React项目。我们学会了用Vite初始化项目,并修改了App.jsx组件,让页面显示出我们想要的文字。但是,那个页面是“死”的,它只是静态…...