Java集合框架(二):JDK1.7的ArrayList源码解析 | 您所在的位置:网站首页 › arraylist源码17 › Java集合框架(二):JDK1.7的ArrayList源码解析 |
ArrayListJDK1.7变量和常量方法构造新增元素add(E e)方法add(int index,E element)方法
删除元素clear清空集合remove index方法
remove object方法修改元素克隆方法
ArrayList
JDK1.7
我们首先来看看JDK1.7的ArrayList 所以ArrayList拥有AbstractList所有方法,也就是有一些Collection接口的默认实现和List接口的默认实现 变量和常量接下来,我们看看ArrayList里面有哪些变量和常量 方法的话,我们从构造、增加、删除、查看、修改去看ArrayList 构造
如果没有确定容量,也就是使用第二个构造方法,会有以下几个步骤 super调用AbstractList的构造方法,来实例化父类将底层数组设为EMPTY_ELEMENTDATA,也就是一个空数组好像在更早期的时候JDK1.7版本是直接调用this(10)来构造的,视频看到的,我也不知道什么版本相比于直接this(10)去实例化ArrayList,直接将底层数组设置为一个空数组更加节省内存,因为不知道你实例了之后到底去不去用,不用的话,那这个空间就浪费了,所以当要add的时候才进行给底层数组申请内存空间 新增元素
这个方法分为三步 检查底层数组容量是否足够(是否可以再增加元素),minCapacity就是代表新增了元素之后,底层数组里面此时总共有多少个元素(注意这里是还没有新增的,新增的操作是下一步)底层Object数组增加元素,位置在size(size记录了底层数组的元素个数,那么新的元素在数组的索引位置就是size),然后size++返回true,表示新增成功后面两部都很容易理解,关键在于ensureCapacityInernal这里 我们来看看他是怎么实现的 接下来进入到ensureExplicitCapacity modCount:这个变量是在AbstratList中的,根据文档来看,是用来记录底层数组修改过的次数 接下来判断新增需要的数组容量是否大于此时底层Object数组的长度 如新增需要的数组容量不大于底层Object数组的长度,就不需要进行操作,直接返回,执行下一步的新增元素如果新增需要的数组容量大于底层Object数组的长度,那么就需要进行扩容,调用grow方法扩容(超重点) 扩容方法是调用grow方法 使用oldCapacity记录此时底层Object数组的长度 newCapacity记录扩容后新数组的长度,规则为旧的长度的1.5倍(右移一位,所以这里后面的0.5倍是一个向下取整) 判断扩容后新的长度是否满足需要,即是否大于minCapacity(增加元素需要的最小空间) 如果不满足需要,即newCapacity小于minCapacity,那就让newCapacity变为minCapacity,直接让扩容后的容量为增加元素需要的最小空间接下来判断扩容后的数组长度是不是大于MAX_ARRAY_SIZE(这个值为Integer的最大值减去8) 如果大于MAX_ARRAY_SIZE,就会调用hugeCapacity(但这个方法不是再AbstractCollection已经有实现了吗?直接调用不行吗?)
最后调用Arrays.copyof方法来讲旧数组原有的数组转移到新数组中,然后讲新数组赋值给elementData变量,相当于扩容产生了另外一个新数组 至此,扩容就结束了 add(int index,E element)方法接下来我们看另一个add方法,指定位置去增加元素 由于ArrayList的底层是一个Object数组,所以指定位置去增加元素,因为往数组中增加元素是需要进行复杂操作的,增加的位置后面的那些元素都要往后移一位 首先调用rangeCheckForAdd来看要插入的位置(index)是否合理 接下来到判断底层数组容量是否足够(即上面提到的扩容) 然后调用System.arrayCopy方法,将底层数组从index位置后面的元素都往后移动一格,即腾出index的位置 接下来让底层Object数组的index索引对应的值设为指定值 最后让size自增 该方法为void型,不会有返回值 删除元素 clear清空集合
注意,这里gc回收的是数组里面的引用对象,而不是数组的内存 所以,此时底层Object数组的长度依然是之前的,这样做的好处就是,下次再继续add的时候,就不再需要进行扩容 remove index方法
步骤如下 modCount自增1使用elementData获取旧的元素使用arrayCopy的方法将后面的元素移上前来,空出了最后一个底层数组位置将底层数组最后一个位置设为null,让gc收集引用的内存将旧的元素返回 remove object方法
通过遍历底层数组,然后使用equals方法进行比较底层数组的各个元素,找到匹配的索引,然后调用fastRemove方法 接下来看看fastRemove方法是怎样的 不太懂为什么要叫fastRemove,哪里fast了?? 修改元素修改元素对应的方法就是set,而该方法是有返回值的,返回被替代或被修改的元素 第一步同样是检查index是否合理(与add第二种方法一样) 调用ekementData根据Index索引获取旧的元素 然后修改底层Object数组指定索引对应的值即可 克隆方法这里再拓展以下ArrayList的clone方法 这里catch用了前面复习java异常提到过的,使用catch来改变异常的类型 回到clone方法这里,这个clone方法是重写Object的 调用父类的clone方法,这里对应的是调用Object的clone,拷贝一个ArrayList然后将拷贝出来的新ArrayList的底层数组复制当前ArrayList的elementData然后将拷贝出来的新ArrayList的modCount设置为0,代表为新的,底层Object数组没有改动过不过有点疑问,为什么拷贝出来的ArrayList可以直接点出私有属性出来??? 看网络上的回答,私有的意思是不让外界访问本类(实现对外隐藏保护),那么该类在该类自己的clone方法里面拷贝的另一个对象的类型也是属于本类,那么就不应该限制访问,因为这就相当于限制自己访问自己的私有东西,是不合理的。 |
CopyRight 2018-2019 实验室设备网 版权所有 |