sheng的学习笔记-ArrayList源码分析

概述

ArrayList就是动态数组,它提供了动态的增加和减少元素,实现了Collection和List接口,可以灵活的设置数组的大小。要注意的是ArrayList并不是线程安全的,因此一般建议在单线程中使用ArrayList。

数组:通过代码看得出来,新增,删除元素都可能伴随着内存拷贝,所以速度慢,但通过索引查找元素速度很快

我的版本是JDK 1.7,不同版本的源码不同

内存模型:

 

ArrayList底层是个object数组,还有个size,这俩变量很重要

 

 初始化

初始化构建默认10个元素的数组

1.8以后初始化的时候默认构建空数组,在第一次add的时候才会扩容到10个长度数组

 新增元素

新增元素(不传入元素增加的位置)

看容量够不够,不够的话扩容

将元素放到数组中,size+1

 扩容逻辑

minCapacity是需要的最小容量,在新增一个元素时是size+1。如果数组的长度小于需要的最小荣浪(不够了)会扩容

扩容时,

  1. 根据元素数组的长度,计算出新的需要扩大到多少容量,计算逻辑:新增一半的容量(oldCapacity右移1就是除以2)。
  2. 如果计算出的结果newCapacity小于需要的最小容量minCapacity,就扩容到minCapacity,
  3. 如果计算出的结果newCapacity超过最大值2147483639(private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;)就扩展到指定的大小(具体看hugeCapacity函数)
  4. 将元素复制到新的数组中,注意,复制元素到数组涉及到内存复制,耗费资源,频繁进行这种动作速度会变慢,要是预计知道有多少个元素,在初始化的时候明确设置大小,避免自动扩容

 

新增元素(传入元素增加的位置)

这种方式会有内存拷贝,消耗资源较大,速度也慢,没有特别的需求别用这个

  1. 校验index不能大于size和不能小于0
  2. 扩容
  3. 数组的内存拷贝,将index之后的数据(index到结尾的所有数据),挪到elementData的index+1的位置,不需要新申请内存,但有内存拷贝,耗费资源
  4. 将传入的元素放到数组的制定位置,size++

 

删除元素

根据索引删除

除非删除结尾的元素,不然会有内存拷贝,速度慢

  1. 找到索引对应元素(用于返回)
  2. 计算需要挪的数据长度(如果删除的是最后一个就不需要内存拷贝),内存拷贝,从index+1的位置挪到index的位置
  3. 最后一个元素值为null

 根据对象删除

遍历数组,找到对象后,拷贝数组内存,删除元素

 

 

查找数据

根据元素查找(返回索引)

分为是不是null,如果是null,看哪个元素等于null,如果不是null,根据equals判断是否相等

从0开始往后查,速度比较慢,还有个lastIndexOf函数从后往前差

根据索引查找

rangeCheck:检查下所以是否超过size

直接根据索引查找数组

设置数据

根据索引查找下老的元素,将新的元素替换到索引对应的位置

 

 

 拷贝数据

clone是浅拷贝

 在这里插入图片描述

 

修减容量trimToSize

ArrayList是动态扩容的,每次扩容都是1.5倍,到后来可能造成空间浪费,用这个函数可以缩减空间(有多少个元素申请多少空间,避免浪费),而且没有返回值,纯操作函数

 马士兵老师Java集合全套视频_零基础Java小白必学框架源码教程:Hashmap底层原理分析——ArrayList,HashSet,List,TreeMap_哔哩哔哩_bilibili

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值