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

ArrayList源码解析

类结构

类继承体系

在这里插入图片描述

  1. 继承自AbstractList(顶级为Collection接口)
  2. 实现了List接口,实现了集合运算、集合增删改查的方法
  3. 实现RandomAccess接口,这只是一个标志接口,里面没有方法,区别于LinkedList,表示ArrayList更适用于随机访问,即fori循环行性能比迭代器性能高
  4. 实现Cloneable接口,可以调用clone方法进行深拷贝
  5. 实现Serializable接口,可以使用ObjectInputStrem、ObjectReader等进行序列化与反序列化

核心属性

在这里插入图片描述
elementData是ArrayList底层的数据结构,即Object数组;transient关键字表示该变量无法被序列化,防止序列化破坏ArrayList的封装性
size是ArrayList对象的有效元素大小,当size增加到数组的容量时,将会触发扩容
在这里插入图片描述

这是ArrayList从AbstarctList继承来的属性,表示结构变化次数,每次扩容、删除等都会引起modCount的改变,它用于迭代器的快速失败,如果在迭代过程中出现了对ArrayList的修改导致modCount变化了,即结构发生变化,则迭代器会抛出Concurrent Modification Exception

ArrayList创建与基本使用

空参创建与首次扩容

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

通过空参构造器创建的ArrayList底层是一个空数组,在第一次添加元素时,这个常量将会被用于判断是否是空参构造的ArrayList,如果是空参构造的数组,在第一次添加元素进行扩容时,会被扩容为10
在这里插入图片描述

在这里插入图片描述

带参创建与扩容

传入指定容量

在这里插入图片描述
在这里插入图片描述

通过传入一个int类型可以指定底层数组的初始大小,现讨论传入0的特殊情况,这里底层同样会被初始化为空数组,但是区别于空参构造器,两者指向的并不是同一个对象,所以这里不会像空参构造一样在第一次扩容为10

在这里插入图片描述
在这里插入图片描述

传入已有集合参数

因为ArrayList底层使用的是Object数组,所以这里将数组转成Object类型
在这里插入图片描述

删除元素

根据索引删除

在这里插入图片描述

根据元素删除

在这里插入图片描述

根据索引区间删除

在这里插入图片描述

通过过滤器指定条件删除removeIf

在这里插入图片描述

修改元素

在这里插入图片描述
由此可见,ArrayList的set方法只能用来修改元素,不能用来增加元素,如果set方法传入的index在list长度之外,会在rangeCheck时报错IndexOutOfBoundsException

查询元素

在这里插入图片描述

ArrayList中常用方法

继承自List的集合处理方法(源码从上至下)

size和isEmpty

在这里插入图片描述

contains和indexOf

在这里插入图片描述

toArray

在这里插入图片描述
注意,这里的两个toArray方法不光实现了List接口还实现了AbstractCollection接口,可能有疑问实现的到底是哪个接口的方法,其实多虑了,这两个接口中任何一个类型的引用都可以传入ArrayList实例来调用这一段方法,下面这段代码佐证了这一点

public class Test {
    public static void main(String[] args) throws Exception {
        Method m = Class.forName("A").getDeclaredMethod("a");
        Method m2 = Class.forName("B").getDeclaredMethod("a");
        C c = new C();
        m.invoke(c);
        m2.invoke(c);
    }
}

interface A{
    void a();
}
interface B{
    void a();
}

class C implements A,B{

    @Override
    public void a() {
        System.out.println("a");
    }
}

clear

在这里插入图片描述

addAll

在这里插入图片描述

removeAll和retainAll

在这里插入图片描述

replaceAll和sort

在这里插入图片描述

序列化方法

  • 上面核心属性部分可以看到,elementData被transient修饰,是不能直接通过ObjectOutputStream序列化的,而ArrayList又继承了序列化方法,具体的序列化方式如下
  • ArrayList继承了Serialziable接口,表示ArrayList是可序列化的,它内部定义了readObject和writeObject方法,在序列化时,如果对象定义了这两个方法,则JVM会调用这两个方法来进行用户自定义的序列化和反序列化,没有定义则使用则默认调用是 ObjectOutputStream 的 defaultWriteObject 方法以及 ObjectInputStream 的 defaultReadObject 方法
    在这里插入图片描述

在这里插入图片描述

其他方法

修剪集合大小trimToSize

在这里插入图片描述

clone方法

在这里插入图片描述

forEach方法

在这里插入图片描述

内部类

迭代器

ArrayList中定义了两个内部迭代器类:Itr、ListItr,其中Itr实现了Iterator接口,ListItr是Itr的子类

Itr

属性
在这里插入图片描述
构造器
在这里插入图片描述
方法
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

ListItr

ListItr是Itr的优化版本
构造器
在这里插入图片描述
方法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

获取迭代器的方法

在这里插入图片描述

子视图

ArrayList中还有一个内部类SubList,用于从ArrayList中截取部分子视图
属性
在这里插入图片描述
子视图的方法和ArrayList基本一致,不做过多重复的分析,子视图的每一次操作都是利用ArrayList.this.elementData进行的,所以会直接修改ArrayList

获取子视图的方法

在这里插入图片描述

ArrayListSpliterator

ArrayListSpliterator是1.8加入的分割迭代器,相较于普通的Iterator迭代器,它的资源消耗更少,不需要next和hasNex配合,一个tryAdvance操作就可以完成迭代,而且分割迭代器还可以进行分区迭代

属性
在这里插入图片描述
构造器
在这里插入图片描述
方法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

相关文章:

  • iptables防火墙 (SNAT、DNAT)
  • idea2021.3.3 创建maven-scala项目并解决遇到的问题:通过add frameworks support找到不到scala插件
  • 模板模式【Java设计模式】
  • openGL 材质
  • windows 10 局域网设置固定 IP 地址
  • Python之猜数字游戏
  • Python 程序的输出 | 第十套(异常处理)
  • 【Android入门】8、Service 后台线程、多线程、IntentService
  • 面向医学图像语义分割-MedISeg
  • puzzle(017.9)HueBots
  • SIM卡被锁怎么办
  • 腾讯云服务器有那么多的型号标准型,计算型,内存型等等,到底该如何选择?
  • 【Android入门】6、ContentProvider:跨程序的数据共享:访问其他 App、被其他 App 访问
  • 文献学习(part102-A)--Autoencoders
  • SS-Model【6】:U2-Net
  • [nginx文档翻译系列] 控制nginx
  • 【前端学习】-粗谈选择器
  • Android优雅地处理按钮重复点击
  • axios 和 cookie 的那些事
  • Docker 笔记(2):Dockerfile
  • echarts花样作死的坑
  • ES6系列(二)变量的解构赋值
  • Git学习与使用心得(1)—— 初始化
  • JAVA_NIO系列——Channel和Buffer详解
  • Shell编程
  • 持续集成与持续部署宝典Part 2:创建持续集成流水线
  • 从零开始在ubuntu上搭建node开发环境
  • 给github项目添加CI badge
  • 基于OpenResty的Lua Web框架lor0.0.2预览版发布
  • 硬币翻转问题,区间操作
  • 终端用户监控:真实用户监控还是模拟监控?
  • Android开发者必备:推荐一款助力开发的开源APP
  • 积累各种好的链接
  • 基于django的视频点播网站开发-step3-注册登录功能 ...
  • 数据可视化之下发图实践
  • ​RecSys 2022 | 面向人岗匹配的双向选择偏好建模
  • #define用法
  • $.ajax()
  • (+3)1.3敏捷宣言与敏捷过程的特点
  • (12)Hive调优——count distinct去重优化
  • (14)学习笔记:动手深度学习(Pytorch神经网络基础)
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • (C语言)逆序输出字符串
  • (c语言版)滑动窗口 给定一个字符串,只包含字母和数字,按要求找出字符串中的最长(连续)子串的长度
  • (echarts)echarts使用时重新加载数据之前的数据存留在图上的问题
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (九)信息融合方式简介
  • (六)什么是Vite——热更新时vite、webpack做了什么
  • (十六)串口UART
  • (原)记一次CentOS7 磁盘空间大小异常的解决过程
  • (原创)boost.property_tree解析xml的帮助类以及中文解析问题的解决
  • (转)程序员技术练级攻略
  • .md即markdown文件的基本常用编写语法
  • .NET Core 网络数据采集 -- 使用AngleSharp做html解析
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地中转一个自定义的弱事件(可让任意 CLR 事件成为弱事件)