ArrayList补充

构造方法

ArrayList共有三种构造方法:

1. 无参构造

​ 创建一个长度10的Object数组。

2.参数是int型 [0~2^31-1)

​ 若参数大于0,创建指定长度的Object[];

​ 若参数等于0,Object类型的空数组

​ 其他情况,抛出异常。

3.参数是Collectinon

​ 创建一个包含集合c所有元素的List,元素集合和集合Iterator遍历得到的元素顺序一样。

void trimToSize()

若List中元素个数小于List长度,进行判断:

元素个数为0,trim后返回空Object数组;

否则的话通过Arrays.copyOf(Object [], int size)进行trim。

扩容函数

//以下是ArrayList的部分源码
public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

private static int calculateCapacity(Object[] elementData, int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
       return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;
    // overflow-conscious code
    if (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);
}

void grow(int minCapacity)

ArrayList扩容的核心函数。每次扩容后至少是原容量的1.5倍,若1.5倍容量仍不够,那么newCapacity直接设为minCapacity。最后如果newCapacity > MaxArrraySize 的话,使用hugeCapacity(int )比较minCapacity和MAX_ARRAY_SIZE的大小,如果前者大,那么新容量就是Integer.Max_Value,否则就是MAX_ARRAY_SIZE。

也就是说:ArrayList并非是无限大的,它最大可以扩容到2^31-1。

**注:**MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8,这里减8的原因是需要8bit存储元信息。

boolean add(E e)

添加时先调用ensureCapacityInternal(int minCapacity)方法把数组容量增加1;

然后将待添加的元素加入。

ensureCapacityInternal(int minCapacity)

该函数调用利用ensureExplicitCapacity()函数得到最小扩容量。

calculateCapacity()

calculateCapacity(Object[] elementData, int minCapacity)计算最小空间:

若elementData为空,那么返回max(10, minCapacity);否则返回minCapacity。

remove函数

删除的时间复杂度为 O(N)

public E remove(int index) {
        rangeCheck(index);//检查index是否合法

        modCount++;
        E oldValue = elementData(index);//获取被删除的元素

        int numMoved = size - index - 1;//删除一个元素后,后面要向前移动的元素的个数
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work
	    //都向前移一位,所以最后以为置为null并将size-1
        return oldValue;
    }

fastRemove (int index)

用于remove(Obj o),较于remove(int index)只少了对index合法性的检测,以及不返回被删除的元素。

序列化

ArrayList 基于数组实现,并且具有动态扩容特性,因此保存元素的数组不一定都会被使用,那么就没必要全部进行序列化。

保存元素的数组 elementData 使用 transient 修饰,该关键字声明数组默认不会被序列化。

序列化时需要使用 ObjectOutputStream 的 writeObject() 将对象转换为字节流并输出。而 writeObject() 方法在传入的对象存在 writeObject() 的时候会去反射调用该对象的 writeObject() 来实现序列化。反序列化使用的是 ObjectInputStream 的 readObject() 方法,原理类似。

Fail-Fast

modCount 用来记录 ArrayList 结构发生变化的次数。结构发生变化是指添加或者删除至少一个元素的所有操作,或者是调整内部数组的大小,仅仅只是设置元素的值不算结构发生变化。

在进行序列化或者迭代等操作时,需要比较操作前后 modCount 是否改变,如果改变了需要抛出 ConcurrentModificationException。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值