首页 > 学院 > 开发设计 > 正文

ArrayList源码分析

2019-11-15 01:12:33
字体:
来源:转载
供稿:网友
ArrayList源码分析

ArrayList是java中最常使用的动态数组,其具体使用方式就不再介绍,本文只是从源码角度介绍它内部的序列化和扩容机制。ArrayList作为集合框架中的一员,它的继承关系如下所示:

image

public class ArrayList<E> extends AbstractList<E> implements Cloneable, Serializable, Randomaccess

从它实现的接口来看,ArrayList支持clone,序列化,随机访问。在类中维持了两个成员变量:

int size;transient Object[] array;

其中size是ArrayList的长度,array是一个object类型的数组用于存储数据元素,元素本身也可以为null。等等,这里为什么事transient来修饰的呢?说好的序列化呢?

原来,ArrayList并没有使用默认的序列化机制,而是实现了readObjectwriteObject 方法来完成序列化工作:

PRivate void writeObject(ObjectOutputStream stream) throws IOException {        stream.defaultWriteObject();        stream.writeInt(array.length);        for (int i = 0; i < size; i++) {            stream.writeObject(array[i]);        }    }    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {        stream.defaultReadObject();        int cap = stream.readInt();        if (cap < size) {            throw new InvalidObjectException(                    "Capacity: " + cap + " < size: " + size);        }        array = (cap == 0 ? EmptyArray.OBJECT : new Object[cap]);        for (int i = 0; i < size; i++) {            array[i] = stream.readObject();        }    }

这种方法比默认的机制更为高效,它并未存储整个数组中的null,这样节省了很多空间。

解释完序列化的疑问,我们来看一下它的动态增长机制,在add方法中:

public boolean add(E object) {        Object[] a = array;        int s = size;        if (s == a.length) {            Object[] newArray = new Object[s +                    (s < (MIN_CAPACITY_INCREMENT / 2) ?                     MIN_CAPACITY_INCREMENT : s >> 1)];            System.arraycopy(a, 0, newArray, 0, s);            array = a = newArray;        }        a[s] = object;        size = s + 1;        modCount++;        return true;    }

我们可以看到,当数组容量不足对数组扩容的时候,有一个判断:当前长度是否是最小增长长度(MIN_CAPACITY_INCREMENT 12)的1/2,如果小于则按最小增长长度进行扩容,否则扩容为当前容量的3/2.

以上便是ArrayList源码学习中需要注意的两个疑问。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表