Java容器一:ArrayList

ArrayList

List,RandomAccess,Cloneable,Serializable

–>AbstractList–>AbstractCollection


fail-fast的特性,每次扩容后的容量为当前容量+当前容量/2。

静态常量

// 默认初始化大小
private static final int DEFAULT_CAPACITY = 10;
// 默认初始化数组
private static final Object[] EMPTY_ELEMENTDATA = {};
// 同样的默认初始化数组,1.8新增
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

成员变量

// 底层数组
transient Object[] elementData; // non-private to simplify nested class access
// 元素数量
private int size;

初始化时可使用带参数的构造函数ArrayList(int initialCapacity),此时会构造一个指定大小的底层数组作为ArrayList的实现。若使用默认的无参构造函数,此时仅使用一个空的数组作为ArrayList的实现。

this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

ArrayList的无参构造指定一个static final的空数组作为底层实现,并在第一次对ArrayList进行更改的时候将其容量扩大为DEFAULT_CAPACITY或更大。注意,若在有参构造函数传入0作为参数,elementData同样会直接指向一个static final的空数组。

扩容

// 数组最大长度
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
// 每次扩容为原来的1.5倍
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);
}
// 若超过最大容量,尝试以Integer.MAX_VALUE开辟空间
private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}

clone的使用

clone()返回对象的一个浅复制,如果对象是基本类型或其包装类型,则相当于对其进行复制,若是其他对象,则仅复制其引用。

fail-fast

ArrayList不是线程安全的,若使用iterator()得到了迭代器,随后在其他线程进行了增加或删除操作,在当前线程使用迭代器进行next(),previous(),add(),remove()等操作时,均会抛出ConcurrentModificationException(继承至RuntimeException)。

具体实现:

ArrayList中定义了modCount变量,若在AbstractList(ArrayList)中进行了添加删除操作,则modCount的值均会进行增加。在使用iterator()得到迭代器时,迭代器将复制modCount的值,并在进行next(),previous(),add(),remove()等操作前检验该值是否AbstractList(ArrayList)中的值相同,若不相同,则抛出ConcurrentModificationException异常。并在成功进行添加删除操作后将该值与AbstractList(ArrayList)的值进行同步。

添加删除操作的底层实现

ArrayList在进行add(),remove()等操作时,底层是通过调用

System.arraycopy(Object src,  int  srcPos, Object dest, int destPos, int length);

方法将需要移动的内存进行前移或后移。同时将不需要的内存置null保证gc的顺利进行。

subList和Iterator的安全性

subList(int fromIndex, int toIndex)方法并没有新建一个ArrayList对象,而是通过一个内部类SubList(extends AbstractList)(里面包含子表相对于原表的偏移量,通过直接调用ArrayList的方法进行操作)。在创建SubList时同样将modCount进行了复制,若在SubList中进行增加删除操作会更新modCount的值,但若在ArrayList中或其他线程中进行增加删除操作,修改了ArrayList中的modCount的值,则再次通过subList对List进行修改,则会抛出ConcurrentModificationException异常。

public void SublistTest(){
    ArrayList<Integer> list = new ArrayList<>();
    list.add(1);
    list.add(2);
    list.add(3);
    List<Integer> subList = (List<Integer>) list.subList(1, 2);
    list.add(4);
    //java.util.ConcurrentModificationException
    subList.set(0, 1);  
}

不管是通过iterator()或subList()修改ArrayList中的值,一旦拿到Iterator或SubList对象后,若通过其他方式修改ArrayList的值,均会抛出ConcurrentModificationException异常。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值