一、ArrayList就是一个类,内部封装了Object[]用于存取数据。
@Test
public void testArrayList(){
List list = new ArrayList<>();
for (int i = 0; i < 100000; i++) {
list.add(i);
list.get(i);
}
}
二、ADD方法:
主体逻辑:当插入一个元素时,先判断一下数组还有没有位置可以插入,如果没有先扩容。然后存放数据。
扩容原理:
1、插入式数组为空,则copy一个长度为10的数组来替换原有数组
2、正常扩容逻辑,如果不够用copy一个长度为原来长度1.5的数组替换
3、当正常扩容到Integer.MAX_VALUE - 8后,又放满了,则触发最后一次扩容,将数组长度扩到Integer.MAX_VALUE
4、扩容的缺点:该扩容机智会不断的让原来的数组游离,会对GC造成一定的压力,所以如果对长度有预估的情况下,最好直接创建指定长度的list对象,如案例中
new ArrayList<>(100000)比较好
ADD源码核心逻辑注释:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!! //判断数组能不能插入这个元素,如果不能则获取扩容的数组 --1
elementData[size++] = e; // 将e存到index = size的位置
return true;
}
1、
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //如果原数组为空,这时minCapacity肯定为1,则将minCapacity赋值为10
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity); --2
}
2、
private void ensureExplicitCapacity(int minCapacity) {
modCount++; //是扩容的次数
// overflow-conscious code
if (minCapacity - elementData.length > 0) //如果放不下,则扩容:用最低需求的容量-数组长度
grow(minCapacity); --3
}
3、
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); //扩容一般规则:新长度 = 1.5倍的老长度,不含小数。10到15到22到33到49......
if (newCapacity - minCapacity < 0) //空数组扩容
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0) //数组最后一次扩容触发条件Integer.MAX_VALUE - 8,数组能达到的最大长度还是为Integer.MAX_VALUE
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
三、GET方法:
GET就没啥好说了的,传入的下标和size比较下,越界就抛异常,没越界就拿数据
public E get(int index) { rangeCheck(index); return elementData(index); }
private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }