-
Notifications
You must be signed in to change notification settings - Fork 780
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
2019-05-28:谈一谈ArrayList的扩容? #64
Comments
学习目标:
先来看看构造方法 无参数构造方法 /**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
} 这是无参数的构造方法,是对elementData(元素的数组)进行赋值DEFAULTCAPACITY_EMPTY_ELEMENTDATA(空数组,我们暂时叫做默认空数组),明明是空数组,但是注释确实创建容量是10。好吧继续往下看。 再来看带参数的构造方法 public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
//如果initialCapacity>0,创建initialCapacity个元素的数组
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
//等于0时,创建空数组
this.elementData = EMPTY_ELEMENTDATA;
} else {
//否则直接抛出异常
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
} 再看另一个构造方法 public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
} 就是直接将集合转为数组赋值给elementData,同时对size赋值,并且如果size不等于0时,c.toArray might (incorrectly) not return Object[] (see 6260652)。我也是一脸懵逼。等于0时,直接赋值空的数组。 我们接着看add方法,先看一个参数的 public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
} 就是ensureCapacityInternal(size + 1) 并且将e添加到size++的位置,我们来看ensureCapacityInternal(size + 1)方法。 private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
} 看这里 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
} 还记得空参数的构造方法吗?DEFAULT_CAPACITY = 10。也就是当空参数时创建ArrayList时,minCapacity与DEFAULT_CAPACITY的最大值,显然创建无参数构造方法时minCapacity = 0.这时结果 = 10,然后看ensureExplicitCapacity(minCapacity) private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
} 显然调用无参数构造方法时minCapacity - elementData.length > 0是成立的,我们再看grow(minCapacity) 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是元素个数newCapacity是oldCapacity+oldCapacity/2,即oldCapacity的1.5倍。当1.5倍的元素个数小于minCapacity时newCapacity = minCapacity。显然创建无参数ArrayList就是这种情况,这就解决了开头的第一个问题。调用无参数构造方法创建的是10个元素的长度。 我们再看当1.5倍元素个数大于 MAX_ARRAY_SIZE时newCapacity = hugeCapacity(minCapacity); private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
} 到这里我们可以总结一下了: 附加一个问题有没有哪位大神解释下为什么是int最大值减8?网上有人说是因为数组对象用这8位来存储数组长度,锁对象,描述对象状态的标志集合。不是很理解 |
我这里简单说一下 那么为什么需要扩容呢?对象的长度比存储他的数组容量大 这时候需要分两种情况 |
初始容量为10 ,当添加第11个元素的时候,会扩容1.5倍,当添加到16个元素的时候扩容为15*1.5=22,以此类推。 |
|
1.对象头和数组元数据的开销: |
这是来自QQ邮箱的假期自动回复邮件。
|
No description provided.
The text was updated successfully, but these errors were encountered: