集合(一)ArrayList源码分析

集合(一)扒掉ArrayList的外衣

集合(二)LinkedList源码分析

集合(三)HashMap源码分析

ArrayList是什么?

 颤抖的小手敲开门ArrayList的大门,发现她竟然是Object[] elementData数组。

构造函数

我们在使用集合的时候都知道集合长度是随着插入删除变化的,而在创建数组时时需要指定长度的,那ArrayList是如何做到长度可变数组呢

我们发现ArrayList有两个构造函数,一个无参(我们经常用)一个有参(传入一个int值,这个int就是初始数组的长度)

无参构造会在我们插入数据时候默认数组长度为10,当我们在创建时指定了长度,就是初始化数组的长度。

这里有一个关键字transient,这个关键字的作用就是在序列化时忽略该变量,ArrayList是集成Serializable的可以序列化反序列化操作的。

add数据 

我们在使用集合时可以无限的添加数据的,这默认长度10,ArrayList是如何做到扩容的

 这10只是数组的长度,我们集合的长度是根据size变量来的,集合会在插入数据是size+1然后去和数据的长度比较,如果超出了最大容量,就会创建一个长度为10+10/2(JDK8的操作)长度的数组,然后把原数组的内容复制到新数组中,这就完成了扩容。

ArrayList在添加一个数据时做了三件事:

  1. size+1是否在集合容量之内ensureCapacityInternal(English是不是很吊),其实就是判断是否需要扩容;
  2. 数据添加到索引为size+1这个位置;
  3. 返回true。

看源码会知道,扩容就是扩大之前的容器长度向右移1位。大家也可能注意到默认分配的数组大小为integer的最大值-8,这是因为

一些vm在数组中保留一些头字。尝试分配较大的数组可能会导致OutOfMemory错误:请求的数组大小超过了虚拟机限制(百度翻译- -)。

ArrayList又是如何在指定索引处添加数据呢

集合在指定index插入数据,首先会复制数组index开始到最后一个值的数据,然后在index+1位置开始放,腾出index的位置给新值插入,当然这里面也要先判断容量问题。(如下图在3的位置插入一个新值)

remove删除数据 

我们知道在我们遍历ArrayList的时候删除数据会报错java.util.ConcurrentModificationException ,why?

 移除数据的操作也是copy指定位置+1之后的数组移动到指定位置,直接看图说话。

这就也可解释为什么遍历时移除数据会报错,5覆盖了4的位置,那么5就无法被遍历到了。当然如果我们从大到小遍历就不会出现这个问题了。

 

ArrayList在增删时候需要去copy数据,如果超出最大数组长度还要去扩容什么的,所以说ArrayList的增删效率是低的。

ArrayList的内存连续性使其遍历速度相对较快,所以查找就快。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值