一直想记录自己的学习过程,但始终没有付出实际行动,说来惭愧
感谢您的关注,持续更新,欢迎留言交流~
前言:
虽然面试我们通常是讲ArrayList和数组的区别,但小编觉得,我们有必要去了解一下ArrayList,在我们日常开发上,ArrayList也算得上是一种常用的集合了,接下来就和小编一起来扯下淡吧~
话不多说,直接上源码,以下源码基于JDK1.8 让我们先来看看
ArrayList list = new ArrayList();
list.add("小编是个秃顶的大叔~");
// 默认为 0
private int size;
/**
* Appends the specified element to the end of this list.
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(E e) {
// size[0] + 1 当作参数传入方法
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
接下来我们来看看ensureCapacityInternal()方法
思路:其实就是判断数组是否初始化,未初始化赋初始值 10
// transient是用来反序列化的
transient Object[] elementData;
// 定义一个空数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// 默认容量为 10
private static final int DEFAULT_CAPACITY = 10;
/**
* minCapacity:当前存放值的下标 + 1(size + 1)
*/
private void ensureCapacityInternal(int minCapacity) {
// 判断elementData是不是默认的空数组
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
// 取得两个参数中的最大值:DEFAULT_CAPACITY --> 10
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
// minCapacity = 10
ensureExplicitCapacity(minCapacity);
}
接下来我们看看ensureExplicitCapacity()方法:
扩容的大致整体思路:
1.判断这个集合是否达到扩容的标准
2.若扩容之后的长度比插入的这个当前的容量还小,则扩容的容量 = 当前容量(minCapaccity)
3.如果扩容的大小比ArrayList的最大长度还大 如何处理【hugeCapacity方法】
private void ensureExplicitCapacity(int minCapacity) {
modCount++;//modCount是记录修改次数 与线程安全有关系
// 判断是否达到扩容的条件: 当前容量 > 数组长度
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// 赋值以前的容量
int oldCapacity = elementData.length;
// 当前容量为:old容量 + (old容量 / 2) 对于>>不懂的,小编后边会专门写一篇博客
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 扩容后的容量 小于 当前容量
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 扩容后的容量 大于 arraylist最大容量时
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);
}
// 小编觉得很有必要讲一下这个方法:扩容之后大于ArrayList的最大容量执行的hugeCapacity方法
有这么几个疑问:
1.为什么ArrayList的最大数组大小(MAX_ARRAY_SIZE)是:Integer.MAX_VALUE - 8?
2.为什么Integer.MAX_VALUE用0x7fffffff表示?
3.如果当前容量 大于 最大容量则赋值数组长度为Integer.MAX_VALUE,明明已经大于最大容量了?
/**
* The maximum size of array to allocate.
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* A constant holding the maximum value an {@code int} can
* have, 2<sup>31</sup>-1.
*/
@Native public static final int MAX_VALUE = 0x7fffffff;
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0)
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
第一个问题:ArrayList的最大数组大小为什么是Integer.MAX_VALUE - 8?
刚开始小编也是到处找资料说是数组需要8 bytes去存储它自己的大小,开始小编觉得这个回答有些敷衍,直到用翻译工具截图翻译,这才解释了源码上这段可恶的英文,偶买噶,无形之中就暴露了小编的英文水平,请替我保密~~,哈哈哈哈哈哈
第二个问题:Integer.MAX_VALUE 为什么用0x7fffffff代表?
ox代表是16进制 7fffffff才是16进制的值,简单的说就是方便运算,计算器能理解的东西,我们不一定能理解。详细可自行Google一下或找本基础教材翻一下。
第三个问题:Integer.MAX_VALUE就是一个最大最大的上线,再大也不能比天王老子Integer的最大值大
关注小编,点个赞留个评论也是对小编莫大的支持,谢谢帅锅
后面持续更新,地中海发型尚未形成,小编仍需努力。。。。
来源:CSDN
作者:一只爱傻笑的羊
链接:https://blog.csdn.net/weixin_39382337/article/details/103965620