ArrayList学习记录(二)

前面记录了ArrayList的构造方法,现在记录一下ArrayList的重点方法的学习。

ArrayList用的最多的两个方法我赌5毛是add和get方法。

public boolean add(E e) {
    ensureCapacityInternal(size + 1);//检查elementData数组的容量是否需要扩容
    elementData[size++] = e;
    return true;
}

先检测一下数组elementData是否需要扩容,如果需要就扩容,检测完就将e对象加入elementData。接下来就进入扩容检测方法。

private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { // 判断元素数组是否为空数组
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); //比较取较大的一方作为扩容的目标容量
    }
    ensureExplicitCapacity(minCapacity);//检查elementData数组的容量是否需要扩容
}

elementData如果等于DEFAULTCAPACITY_EMPTY_ELEMENTDATA,minCapacity变为DEFAULT_CAPACITY或者minCapacity较大的一方,并传入ensureExplicitCapacity方法。

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;//结构性修改加1(可以参考:http://www.cnblogs.com/liuling/p/2013-8-21-04.html)
    if (minCapacity - elementData.length > 0)//如果目标容量比当前数组的容量要大则进行扩容操作
        grow(minCapacity);//扩容操作
}

因为ArrayList是非线程安全的,所以声明了一个modCount对象。

大概意思就是说:在使用迭代器遍历的时候,用来检查列表中的元素是否发生结构性变化(列表元素数量发生改变)了,主要在多线程环境下需要使用,防止一个线程正在迭代遍历,另一个线程修改了这个列表的结构。

如果目标容量比当前数组的容量要大则进行扩容方法grow。

private void grow(int minCapacity) {
    int oldCapacity = elementData.length; // 旧容量
    int newCapacity = oldCapacity + (oldCapacity >> 1); // 新容量为旧容量的1.5    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) // 当minCapacity等于Integer.MAX_ARRAY_SIZE+1的时候这个判断就会成立 抛出数组越界的错误。
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
}

至此,最常用的add方法已经实现。然后就是get方法。

@Override
public E get(int index) {
    if (index > size)//数组越界的情况
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    return (E) elementData[index];
}

最普遍的add方法和get方法至此已经实现。

public void add(int index, E element) {
    if (index > size || index < 0)//数组判断
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));

    ensureCapacityInternal(size + 1);  // 扩容操作
    System.arraycopy(elementData, index, elementData, index + 1,
            size - index);
    elementData[index] = element;
    size++;
}

这个add一样,检查是否数组越界-->检查是否需要扩容-->将数组elementData[index]后面的所有数据从elementData[index+1]开始填充。

简单的例子:elementData={2,3,4,5,6} , index=0,element=1。

System.arraycopy(elementData, index, elementData, index + 1, 5);

-->elementData={0,2,3,4,5,6}//这里是扩容过的elementData 

elementData[index] = element;

-->elementData={1,2,3,4,5,6}

get和add方法已经全部学习了,还有一个常用的方法 indexOf 有点复杂,放到下一篇记录。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值