ArrayList原理
2019-11-30

需要使用到动态数组的时候用的最多的就是ArrayList了,底层其实是Object数组,以下demo基于JDK1.8:

List<Integer> list  = new ArrayList<>();

list.add(1); list.add(3); list.add(2); list.add(4); list.add(7); list.add(5); list.add(6); list.add(2); list.add(2); list.add(2); list.remove(1);

普及小知识点

length:数组的长度length是数组申请的大小,不管有没有值例如Object[] a = new Object[10];数组a的length就是10

size:是list的概念,表示list有效数组的大小,可能一开始list申请了10个大小的Object数组,然后只add了一个数,这个时候length是10,size是1

native:非java语言写的代码,dll文件

首先看add()函数

ensureCapacityInternal看数组需不需要增加保证有位置插入新的值,然后将要插入的值添加到数组中去

 

 点进去ensureCapacityInternal,其实用到了两个函数ensureExplicitCapacity,calculateCapacity,首先看calculateCapacity

 

 看函数的名字也知道计算容器空间就是数组的大小,这里的思路是数组如果为{},就初始化一个Max(10,minCapacity)个位置大小的数组,否则返回minCapacity,经过一顿骚操作后得到minCapacity,传入ensureCapacityInternal函数,就是要生成数组的函数。

然后这里modCount++,modCount是记录操作的次数,还有一个expectedModCount,后面如果对比两个值不一样的时候会抛异常(另说)

然后判断minCapacity最小容器大小是不是比原来的数组的length大,如果大继续调用grow函数

grow函数也很简单记录原始数组的长度,然后新建一个数字newCapacity是原始数组长度的1.5倍(oldCapacity >> 1右移一位就是除以二),如果newCapacity比传入的minCapacity,就等于minCapacity,如果比MAX_ARRAY_SIZE大(可以理解为很大),就给它一个很大的数组空间,然后调用Arrays.copyOf()函数生成新的数组,通俗的讲就是如果你要grow数组的大小,可以我默认就给你增加到原来的1.5倍,什么你告诉我minCapacity比原来的1.5倍还要大,好那听你的用minCapacity,什么你需要申请的数组大小很大很大就给你一个huge的数组,然后我们调用Arrays.copyOf实际生成需要的数组,然后看copyOf()函数

点进去继续看return的copyOf函数

 

 

 这个函数也很简单,就是新建一个copy数组其实就是我们要生成的数组,如果newType是Object类型就新建一个Object的数组,长度是newLength(这里的newType其实就是original.class,就是原始数组的类型的class,newLength就是希望创建的数组的大小),如果原始数组不是Object的就调用Array.newInstance方法生成数组实例,点进去

继续点击进去newArray方法

其实调用的就是底层的native方法,native方法就是不是java语言写的方法,例如可能你调用的是dll文件,就是说你不是Object可能就是其他语言支持的一些类型了

然后继续往后看System.arraycopy

System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));

点进去

其实就是一个native方法

src - 源数组。 srcPos - 源数组中的起始位置。 dest - 目标数组。 destPos - 目标数据中的起始位置。 length - 要复制的数组元素的数量。

直接调用System.arraycopy的话,这里copy的时候如果是两个不同数组还好就是copy,如果传入的是同一个数组实际是对同一个数组进行操作

总的来说就是封装了数组,让我们用起来方便一些没什么,溜了

, 1, 0, 9);