Java源码解析_ArrayList

ArrayList

ArrayList是list adt的一种可增长数组的实现

时间复杂度:

printList:O(N)
findKth: O(1)
删除和插入平均花费线性时间 O(N)

源码分析

1.构造方法

构造方法有三个

public ArrayList()
public ArrayList(int initialCapacity);
public ArrayList(Collection<? extends E> c);

第一个是无参,elementData是保存数据的数组。这里将其赋值为一个默认的空数组

public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
transient Object[] elementData;
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

第二个使用给定的容量来初始化。当参数大于0时,直接初始化给定容量的数组。

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);
    }
}

第三个是用给定的集合初始化,直接将c转成数组赋值给elemenetData。c.toArray()的类型可能不是Object[].class,List strs= Arrays.asList(“hehe”),strs的类型为 [Ljava.lang.String; 所以要用copyof方法转换,这个方法返回的是Object[].class型的,所以就有可能产生当前的list类型错误,如下图所示:
在这里插入图片描述

public ArrayList(Collection<? extends E> c) 
    elementData = c.toArray();
    if ((size = elementData.length) != 0) {
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        // replace with empty array.
        this.elementData = EMPTY_ELEMENTDATA;
    }
}
2. 添加元素

先确保容量,然后set值。

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}
3.扩容: 构造方法中是一个空数组,添加第一个元素时,扩容为10,之后扩容为原容量的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);
}
4. remove,用arraycopy实现。
public E remove(int index) {
    rangeCheck(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

    return oldValue;
}
5.addAll方法没有类型检查,所以List类型的arrayList可以添加实际类型为String的 list
public boolean addAll(Collection<? extends E> c) {
    Object[] a = c.toArray();
    int numNew = a.length;
    ensureCapacityInternal(size + numNew);  // Increments modCount
    System.arraycopy(a, 0, elementData, size, numNew);
    size += numNew;
    return numNew != 0;
}
6.序列化,为什么要讲序列化,大家有没有注意到elementData是用transient修饰的,用transient关键字标记的成员变量不参与序列化过程。

transient Object[] elementData;

        List<String> ints=new ArrayList<>();
        for(int i=0;i<5;i++){
            ints.add(i+"");
        }
        FileOutputStream fos=new FileOutputStream(".\\src\\main\\java\\me\\ffulauh\\javalang\\collectiondemo\\list\\list");
        ObjectOutputStream oos=new ObjectOutputStream(fos);
        oos.writeObject(ints);

        FileInputStream fis=new FileInputStream(".\\src\\main\\java\\me\\ffulauh\\javalang\\collectiondemo\\list\\list");
        ObjectInputStream ois=new ObjectInputStream(fis);
        List ints2=(List)ois.readObject();

序列化的时候elementData的长度为10,序列化后,长度为5,证实它没有被序列化。
在这里插入图片描述
在这里插入图片描述
再来看看源码,writeObject中写入的是实际的元素,而不是整个数组

private void writeObject(java.io.ObjectOutputStream s)
    throws java.io.IOException{
    // Write out element count, and any hidden stuff
    int expectedModCount = modCount;
    s.defaultWriteObject();

    // Write out size as capacity for behavioural compatibility with clone()
    s.writeInt(size);

    // Write out all elements in the proper order.
    for (int i=0; i<size; i++) {
        s.writeObject(elementData[i]);
    }

    if (modCount != expectedModCount) {
        throw new ConcurrentModificationException();
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值