ArrayList增删底层源码阅读
来源:互联网 发布:提升搜狗关键词优化 编辑:程序博客网 时间:2024/06/05 05:58
在其他网站看到一篇关于ArrayList的部分源码解析 , 刚好自己也在看这部分东西 , 于是便转载过来 同时也增加了部分自己的内容 仅供大家学习交流 原文出自 https://www.cnblogs.com/aoguren/p/4765439.html
1)在指定位置插入元素时,第一步都需要检查输入的指定位置是否合法
public void add(int index, E element)==>
{
rangeCheckForAdd(index);
...
}
private void rangeCheckForAdd(int index)
{
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
分析:rangeCheckForAdd方法用于检查index是否越界。如果该index大于ArrayList元素个数或者小于0时,抛出索引越界异常。
其中outOfBoundsMsg方法,是用来展示IndexOutOfBoundsException detail message。
private String outOfBoundsMsg(int index)
{
return "Index: " + index + ", Size: " + size;
}
2)在指定位置删除元素时,第一步也需要检查输入的索引号是否合法
public E remove(int index)==>
{
rangeCheck(index);
...
}
private void rangeCheck(int index)分析:rangeCheck方法只需检测index索引是否超出ArrayList元素个数。
{
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
二、确保容量
1)增加容量
public void add(int index, E element)
{
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1);//size的值是从0开始的, 每一次add()之后, size会只增1
...
}
==>
private void ensureCapacityInternal(int minCapacity)//确保内部容量有效
{
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)//空数组
{
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);//将两者最大的一个数设置为最小有效容量 默认容量为10
}
ensureExplicitCapacity(minCapacity);//确定最终容量
}
其中,minCapacity取与默认值之间的最大值。
ensureExplicitCapacity ==>
private void ensureExplicitCapacity(int minCapacity)
{
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
- size很好理解,就是ArrayList的长度大小,也可理解为ArrayList中已添加的元素个数,这里需要注意:ArrayList允许添加为null的元素,所以null也会占用一份空间。
- elementData就是ArrayList的内部数组实现,它是一个一维对象数组。当通过add方法向ArrayList中添加元素时,这些元素就会被依次存储于elementData这个数组中。 elementData既然是数组,它必然拥有长度length,那么这个数组的长度是否等于ArrayList的size?
这里需要了解一些ArrayList的相关设计概念:
1、作为ArrayList的内部实现数组elementData具备一定的长度(初始值为10),此长度又被称为capacity(容量)。
注意:elementData.length等于elementData.size(),但是ArrayList中的size是记录ArrayList元素的个数,而elementData是用来存放ArrayList的元素。或者说elementData相当于鞋柜容器,它的容器大小==elementData.length==elementData.size(),而ArrayList的size相当于鞋子双数。
参考:List实现之ArrayList
private void grow(int minCapacity)
{
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
- 得到数组的旧容量,然后进行oldCapacity + (oldCapacity >> 1),将oldCapacity 右移一位,其效果相当于oldCapacity /2,我们知道位运算的速度远远快于整除运算,整句运算式的结果就是将新容量更新为旧容量的1.5倍,
- 然后检查新容量是否大于最小需要容量,若还是小于最小需要容量,那么就把最小需要容量当作数组的新容量,
- 再检查新容量是否超出了ArrayList所定义的最大容量,若超出了,则调用hugeCapacity()来比较minCapacity和 MAX_ARRAY_SIZE,如果minCapacity大于最大容量,则新容量则为ArrayList定义的最大容量,否则,新容量大小则为 minCapacity。 (在判断容量是否超过MAX_ARRAY_SIZE的值,MAX_ARRAY_SIZE值为Integer.MAX_VALUE - 8,比int的最大值小8,不知道为什设计,可能方便判断吧。如果已经超过,调用hugeCapacity方法检查容量的int值是不是已经溢出。一般很少用到int最大值的情况,那么多数据也不会用ArrayList来做容器了,估计这辈子没机会见到hugeCapacity运行一次了。)
- 最后确定了新的容量,就使用Arrays.copyOf方法来生成新的数组,copyOf也已经完成了将就的数据拷贝到新数组的工作。(Arrays.copyof(···)与System.arraycopy(···)区别)
需要注意的是,容量拓展,是创建一个新的数组,然后将旧数组上的数组copy到新数组,这是一个很大的消耗,所以在我们使用ArrayList时,最好能预计数据的大小,在第一次创建时就申请够内存。
参考:ArrayList实现原理以及其在jdk1.6和jdk1.7的实现区别
hugeCapacity ==>
private static int hugeCapacity(int minCapacity)
{
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
2)缩小容量
public void trimToSize()
{
modCount++;
if (size < elementData.length)
{
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}
ArrayList是我们最常用的列表之一 大家多掌握一些肯定是有好处的 多学习 多交流
- ArrayList增删底层源码阅读
- ArrayList源码阅读笔记
- ArrayList源码阅读
- ArrayList源码阅读
- java8 ArrayList源码阅读
- 源码阅读之ArrayList
- ArrayList源码阅读
- ArrayList源码阅读笔记
- ArrayList源码阅读
- Java源码阅读-ArrayList
- JDK源码阅读-ArrayList
- java8 ArrayList源码阅读
- Java源码阅读-ArrayList
- java8 ArrayList源码阅读
- ArrayList源码阅读笔记
- ArrayList底层实现源码解析
- ArrayList底层实现源码解读
- skynet底层源码阅读(1)
- 剑指offer—扑克牌顺子
- Python20行代码实现多层神经网络的学习
- qsv视频文件转换成吗mp4视频文件
- php 运算符
- 微程序控制器之微地址的形成
- ArrayList增删底层源码阅读
- 快速了解IDEA
- 设计模式(十八)——桥接模式
- 端口详解+端口扫描原理+简单端口扫描实现
- 深度学习框架安装(cuda8+cudnn6)
- 开发者应该掌握的Java代码优化技能
- JavaScript之——对象Object(一)
- 命令行开发第一个Servlet程序并简要介绍Tomcat工作流程
- [leetcode]257. Binary Tree Paths[facebook](todo)