public boolean add(E e) {
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0)
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
这里传入的minCapacity什么情况下会出现小于0的情况?还请赐教。
int minCapacity,是有符号的int,要考虑溢出的问题
如果它大于2147483647,那么就会变成负数。
首先int类型是有符号的,结果大到占用了符号位,符号位不为0,就会被认为是负数。int溢出超出了int类型的最大值,如果是两个正数相加,溢出得到一个负数,或两个负数相加,溢出得到一个正数。
https://segmentfault.com/q/1010000006093623
当数组要溢出的时候,就加上数组的1/2,然后和数组最大的常量进行比对,如果超出数组的最大size,就新申请一个Integer.MAX_VALUE的数组,然后把之前旧数组复制过来。
其中最难理解的是>>1,其实相当于除以2。
当minCapacity等于Integet.MAX_VALUE+1时 会出现这个问题,虽然log出来是一串正数但是if(minCapacity < 0) 判断会成立。
ArrayList相当于在没指定initialCapacity时就是会使用延迟分配对象数组空间,
当第一次插入元素时才分配10(默认)个对象空间。假如有20个数据需要添加,那么会分别在第一次的时候,
将ArrayList的容量变为10 ,之后扩容会按照1.5倍增长。也就是当添加第11个数据的时候,
Arraylist继续扩容变为10*1.5=15;当添加第16个数据时,继续扩容变为15 * 1.5 =22个
在JDK1.7中,如果通过无参构造的话,初始数组容量为0,当真正对数组进行添加时,才真正分配容量。
每次按照1.5倍(位运算)的比率通过copeOf的方式扩容。
在JKD1.6中,如果通过无参构造的话,初始数组容量为10.每次通过copeOf的方式扩容后容量为原来的1.5倍加1。
当minCapacity等于Integet.MAX_VALUE+1时 会出现这个问题。希望可以帮到你。