1.ArrayList的主意事项
-
ArrayList可以加入null,并且可以多个
-
ArrayList是由数组来实现数据存储
-
ArrayList基本等于Vector,ArrayList是线程不安全的但是执行效率高,在多线程开发环境中不建议使用。
2.Arraylist的底层操作机制源码分析(重点、难点)
-
ArrayList中维护了一个Object类型的数组elementData
-
源码:transient Object[] elementData; transient表示瞬间、短暂的,表示该属性不会被序列化
-
当创建ArrayList对象时,如果使用的无参构造器,则初始elementData容量为0,第一次添加,则扩容elementData为10,如需要再次扩充,则扩容以elementData的1.5倍扩容
-
如果使用的是指定大小的构造器,初始elementData容量为指定大小,如果需要扩容则扩容以elementData的1.5倍扩容
3.无参构造创建ArrayList对象源码解读:
创建对象时ArrayList无参构造直接给elementData一个空的Object数组
源码:
private static final Object[] EMPTY_ELEMENTDATA = {};这是一个Objec数组的静态常量
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
第一次添加元素
先判断是否需要扩容后添加数据
源码:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
该方法确定minCapacity 第一次扩容10。 Math.max()方法返回一个最大值
源码:
private static final int DEFAULT_CAPACITY = 10;这是一个int静态常量
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
modCount++记录集合被修改的次数 如果elementData大小不够就调用grow()去扩容
源码:
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
-
java移位运算小技巧
-
左移一位相当于乘以2的1次方,左移n位就相当于乘以2的n次方。
-
右移一位相当于除以2的1次方,右移n位就相当于除以2的n次方。
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
@Native public static final int MAX_VALUE = 0x7fffffff;0x7fffffff的值很大:2147483647
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);
}
执行Arrays.CopyOf()完成扩容并把新内存地址给到elementData,
源码:
elementData = Arrays.copyOf(elementData, newCapacity);
之后的扩容就不会进入calculateCapacity() 方法的
if语句而是直接返回minCapacity
源码:
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
最后执行添加语句并返回一个布尔值
源码:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
源码:
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}