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

【Java容器(jdk17)】ArrayList深入源码,就是这么简单

ArrayList深入源码

  • 一、ArrayList源码解析
    • 1. MIXIN 的混入
    • 2. 属性说明
    • 3. 构造方法
    • 4. 其他方法(核心)
      • iterator 和 listIterator 方法
      • add方法
      • remove 方法
      • sort方法
      • 其他
  • 二、ArrayList 为什么是线程不安全的?体现哪些方面呢?
  • 三、ArrayList 细节汇总

前言:
个人觉得看源代码会增进不少知识,一直都是看别人写的博客中的代码片段,没自己静下心来去看过,接下来体验体验源码的快乐。

一、ArrayList源码解析

在这里插入图片描述

对 ArrayList 相应关系有了大致的了解后,咱由外到里依次深入。

1. MIXIN 的混入

ArrayList 利用 MIXIN 的思想,实现了多继承。

说明其实现的接口:

  1. Serializable接口:使得ArrayList 支持序列化和反序列化。
  2. RandomAccess接口:该接口是一个标记接口,意在标明ArrayList 具备快速随机访问的能力,使用for 会比使用 迭代器(iterator)访问速度要快。LinkedList 那边即不具备这种能力,所以不存在这种标记(原因是因为LinkedList 底层是链表,访问都是从根到尾的,所以它使用迭代器会更快)。
  3. 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. 其他方法&#xff08;核心&#xff09;iterator 和 listIterator 方法add方法remove 方法sort方法其他二、ArrayList 为什么是线程不安全的&#xff1f;体现哪些方面呢&#xff1f;三、ArrayLi…...

【Java 面试合集】简述下Java的三个特性 以及项目中的应用

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

git基本概念图示【学习】

基本概念工作区&#xff08;Working Directory&#xff09;就是你在电脑里能看到的目录&#xff0c;比如名字为 gafish.github.com 的文件夹就是一个工作区本地版本库&#xff08;Local Repository&#xff09;工作区有一个隐藏目录 .git&#xff0c;这个不算工作区&#xff0c…...

微前端qiankun架构 (基于vue2实现)使用教程

工具使用版本 node --> 16vue/cli --> 5 创建文件 创建文件夹qiankun-test。 使用vue脚手架创建主应用main和子应用dev 主应用 安装 qiankun: yarn add qiankun 或者 npm i qiankun -S 使用qiankun&#xff1a; 在 utils 内创建 微应用文件夹 microApp,在该文件夹…...

记录robosense RS-LIDAR-16使用过程3

一、wireshark抓包保存pcap文件并解析ubuntu18安装wireshark&#xff0c;参考下面csdn教程&#xff0c;官网教程我看的一脸蒙&#xff08;可能英语太差&#xff09;https://blog.csdn.net/weixin_46048542/article/details/121730448?spm1001.2101.3001.6650.2&utm_medium…...

【博学谷学习记录】大数据课程-学习第七周总结

Hadoop配置文件修改 Hadoop安装主要就是配置文件的修改&#xff0c;一般在主节点进行修改&#xff0c;完毕后scp下发给其他各个从节点机器 文件中设置的是Hadoop运行时需要的环境变量。JAVA_HOME是必须设置的&#xff0c;即使我们当前的系统中设置了JAVA_HOME&#xff0c;它也…...

154、【动态规划】leetcode ——494. 目标和:回溯法+动态规划(C++版本)

题目描述 原题链接&#xff1a;494. 目标和 解题思路 &#xff08;1&#xff09;回溯法 本题的特点是nums中每个元素只能使用一次&#xff0c;分别试探加上nums[index]和减去nums[index]&#xff0c;然后递归的遍历下一个元素index 1。 class Solution { public:int res …...

MySQL-窗口函数

窗口函数概念常用窗口函数聚合窗口函数专用窗口函数语法OVER子句window_specwindow_name (命名窗口)partition_clause 分区order_clause 排序frame_clause 范围 &#xff08;指定窗口大小&#xff09;使用限制练习准备概念 窗口函数对一组查询执行类似于聚合的操作。然而&#…...

【C++设计模式】学习笔记(1):面向对象设计原则

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

[测开篇]设计测试用例的方法如何正确描述Bug

​ 文章目录为什么测试人员要写测试用例&#xff1f;怎样设计测试用例&#xff1f;&#xff08;总的方面&#xff09;1.基于需求设计测试用例&#xff08;总的方面&#xff09; 2.页面&#xff08;总的方面&#xff09; 3.非功能性测试&#xff08;具体方面&#xff09; 4.1 等…...

设计模式学习笔记--单例、建造者、适配器、装饰、外观、组合

以下内容根据以下网址及相关视频整理&#xff1a;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 单选题&#xff1a;She has the face _________.2 单选题&#xff1a; The goals ________ he fought all his life no longer seemed important to him.3 单选题&#xff1a;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&#xfffd; (possibly of length 00). He performed the following operation several (possibly zero)…...

javassm超市在线配送管理系统

为了解决用户便捷地在网上购物&#xff0c;本文设计和开发了一个超市管理系统。本系统是基于web架构设计&#xff0c;SSM框架 &#xff0c;使用Mysql数据库管理&#xff0c;综合采用JSP模式来完成系统的相关功能。主要实现了管理员与用户的注册与登陆&#xff0c;个人中心、用户…...

Scratch少儿编程案例-多模式贪吃蛇(无尽和计时)

专栏分享 点击跳转=>Unity3D特效百例点击跳转=>案例项目实战源码点击跳转=>游戏脚本-辅助自动化点击跳转=>Android控件全解手册点击跳转=>Scratch编程案例👉关于作者...

谷歌蜘蛛池怎么搭建?Google蜘蛛池可以帮助谷歌排名吗?

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

Kubernetes集群-部署Java项目

Kubernetes集群-部署Java项目&#xff08;SSG&#xff09; k8s部署项目java流程图 第一步 打包制作镜像 打包 java源码&#xff1a; application.properties #在有pom.xml的路径下执行 mvn clean package制作镜像&#xff1a; 将刚才打包后的文件夹传到&#xff0c;装有dock…...

English Learning - Day54 作业打卡 2023.2.8 周三

English Learning - Day54 作业打卡 2023.2.8 周三引言1. 就算你不喜欢喝酒&#xff0c;也请尝一杯吧。2. 便纵有千种风情&#xff0c;更与何人说&#xff1f;——柳永《雨霖铃》 (来&#xff0c;挑战一下古诗词)3. 虽然忙&#xff0c;我也要参加会议。4. 无论发生什么&#xf…...

【Unity题】 1.矩阵旋转,欧拉旋转,四元数旋转各自的优缺点。2.StringBuilder和String的区别

1.矩阵旋转&#xff0c;欧拉旋转&#xff0c;四元数旋转各自的优缺点 矩阵旋转&#xff0c;欧拉旋转&#xff0c;四元数旋转是三种不同的旋转表示方法&#xff0c;下面是它们各自的优缺点&#xff1a; 矩阵旋转&#xff1a; 优点&#xff1a; 1.可以方便地实现复合旋转&…...

【C++面试问答】搞清楚深拷贝与浅拷贝的区别

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

day10_面向对象基础

今日内容 零、 复习昨日 一、面向对象的概念 二、面向对象编程 三、内存图 零、 复习昨日 见晨考题 每日一数组题 写一个方法 用于合并两个int类型的数组 合并法则如下 {1,2,5,8,9}{1,3,0}---->{1,2,5,8,9,1,3,0} package com.qf.array;import java.util.Arrays;/*** --- 天…...

电影订票网站的设计与开发

技术&#xff1a;Java、JSP等摘要&#xff1a;随着科技的发展&#xff0c;时代的进步&#xff0c;互联网已经成为了人们生活中不可缺少的一部分&#xff0c;网上购物已然是一种时代的象征。纵观市场&#xff0c;电影行业的发展尤为迅速&#xff0c;电影种类和数量的增多导致客流…...

seata【SAGA模式】代码实践(细节未必完全符合saga的配置,仅参考)

seata SAGA模式&#xff1a; 代码仍然是上一篇AT模式的代码&#xff1a;AT模式 不需要undo_log表 下面开始&#xff1a; 首先&#xff0c;saga模式依靠状态机的json文件来执行整个流程&#xff0c;其中的开始节点的服务即TM&#xff0c;然后状态机需要依靠三张表&#xff0…...

面试题:Java锁机制

java对象包含了三个部分&#xff1a;对象头&#xff0c;实例数据和对齐填充。对象头又存放了&#xff1a;markWord和class point。classpoint &#xff1a;指向方法区&#xff0c;当前对象的类信息数据。markword&#xff1a;存储了很多和当前对象运行时的数据&#xff1a;例如…...

Springboot Web开发

文章目录一. 静态资源访问1. 配置静态资源访问前缀2. 修改默认静态资源存放目录3. Webjars4. 欢迎页支持5. 自定义Favicon二. 请求处理1. 路径变量2. 请求头处理3. 查询字符串处理4. 获取Cookie的值5. 获取请求体的值6. 获取请求域中的数据7. 矩阵变量一. 静态资源访问 只要静…...

分布式事务 | 使用DTM 的Saga 模式

DTM 简介前面章节提及的MassTransit、dotnetcore/CAP都提供了分布式事务的处理能力&#xff0c;但也仅局限于Saga和本地消息表模式的实现。那有没有一个独立的分布式事务解决方案&#xff0c;涵盖多种分布式事务处理模式&#xff0c;如Saga、TCC、XA模式等。有&#xff0c;目前…...

错误代码0xc0000001要怎么解决?如何修复错误

出现错误代码0xc0000001这个要怎么解决&#xff1f;其实这个的蓝屏问题还是非常的简单的&#xff0c;有多种方法可以实现 解决方法一 1、首先使用电脑系统自带的修复功能&#xff0c;首先长按开机键强制电脑关机。 注&#xff1a;如果有重要的资料请先提前备份好&#xff0c;…...

为什么 HTTP PATCH 方法不是幂等的及其延伸

幂等性 首先来看什么是幂等性&#xff0c;根据 rfc2616(Hypertext Transfer Protocol – HTTP/1.1) 文档第 50 页底部对 Idempotent Methods 的定义&#xff1a; Methods can also have the property of “idempotence” in that (aside from error or expiration issues) the…...

13 Day:实现内核线程

前言&#xff1a;我们昨天完成了内核的内存池以及内存管理程序&#xff0c;今天我们要揭开操作系统多任务执行的神秘面纱&#xff0c;来了解并实现一个多任务的操作系统。 一&#xff0c;实现内核线程 在聊线程之间我们先聊聊处理器吧&#xff0c;众所周之现在我们的CPU动不动…...

GPU服务器安装显卡驱动、CUDA和cuDNN

GPU服务器安装cuda和cudnn1. 服务器驱动安装2. cuda安装3. cudNN安装4. 安装docker环境5. 安装nvidia-docker25.1 ubuntu系统安装5.2 centos系统安装6. 测试docker容调用GPU服务1. 服务器驱动安装 显卡驱动下载地址https://www.nvidia.cn/Download/index.aspx?langcn显卡驱动…...

网页设计作业在线网站首页/广告网站建设网站排名优化

完整系列教程详见&#xff1a;http://golang.iswbm.com在 Golang 中用于执行命令的库是 os/exec&#xff0c;exec.Command 函数返回一个 Cmd 对象&#xff0c;根据不同的需求&#xff0c;可以将命令的执行分为三种情况只执行命令&#xff0c;不获取结果执行命令&#xff0c;并获…...

怎样宣传自己的产品/专业网站优化外包

文章转载地址: http://freewind.me/blog/20140327/2456.html问题在某域名下使用Ajax向另一个域名下的页面请求数据&#xff0c;会遇到跨域问题。另一个域名必须在response中添加 Access-Control-Allow-Origin 的header&#xff0c;才能让前者成功拿到数据。这句话对吗&#xff…...

现在做网站有前途吗/seo站点是什么意思

C学习 五、数组与字符串 &#xff08;2&#xff09;字符串字符串字符数组初始化sizeof(), strlen()字符串输入cin.get(char* name, int strsize), cin.get()的混合使用cin.get的失效位string类声明初始化赋值拼接字符访问字符串长度输出字符串后记字符串 字符串可以看作特殊的…...

怎样做网站建设/建设网站流程

图片来自WENN/网络卡莉克劳斯 (Karlie Kloss)图片延伸阅读&#xff1a;Karlie Kloss如今都市年轻人群开始关注健康和生活领域&#xff0c;他们积极追求更健康更多彩的生活方式。他们热爱分享健身技巧&#xff0c;关注青年潮流文化&#xff0c;认真选择自己喜欢的城市&#xff0…...

台州网站建设公司/软文推广发稿

zabbixnotifier官方地址&#xff1a;https://github.com/gigatec/zabbixnotifierzabbixnotifier是一个基于Google Chrome的Zabbix扩展通知程序功能&#xff1a;通过此扩展&#xff0c;Zabbix监控系统的当前状态消息可以直接显示在浏览器中。故障和问题检测可以做到迅速和可靠&a…...

如何用flash做网站/营销技巧培训

环境&#xff1a;VC toolkit 2003 SystemC 2.0.1 为了找出SystemC定义了哪些全局变量/静态变量&#xff0c;我在crt/src/crt0dat.c的 void _initterm(_PVFV * pfbegin, _PVFV * pfend) 函数中设下断点&#xff0c;at Line 598&#xff1a; if ( *pfbegin ! NULL ) …...