集合之ArrayList源码解析

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

 

arrayList 是我们平时开发中最常用的集合了,利用空闲时间来看一下对应源码。

类图如下:

 

实现了接口:List ,RandomAccess, Cloneable, java.io.Serializable

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable

其中RandomAccess, Cloneable, Serializable接口,我们点进去可以发现是空接口,并没有任何实现方法。

RandomAccess表示Arraylist 可以进行快速的随机访问,arraylist 特性为访问速度快,删除添加慢;与之对应的LinkedList 查询慢,删除添加速度快;

Cloneable表示可以进行clone,这个接口起到一个标记作用,告诉jvm 这个可以进行clone ,没有则抛出异常,一般我们实现clone ,先调用supper.clone();

Serializable表示序列化,java序列化是指将java 对象转化为字节序列的过程,反序列化是指将字节序列恢复至java对象的过程。

序列化IO:

  1. java.io.ObjectOutputStream:表示对象输出流 它是OutputStream类的一个子类,对应的ObjectOutputStream.WriteObject(Object object)就要求参数object实现Serializable接口。

  2. java.io.ObjectInputStream:表示对象输入流 ,它的readObject(Object object)方法从输入流中读取字节序列,再把它们反序列化成为一个对象,并返回。

java 中一般我们创建实体类 需要实现 Serializable 接口 ,然后 添加对应的serialVersionUID;

Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,

可以进行反序列化,否则就会出现序列化版本不一致的异常(InvalidCastException)

serialVersionUID 有两种写法:(1)根据类名,接口名,字段属性生成的64位哈希字段 private static final long serialVersionUID = 5490009942423030040L; (2)默认1L private static final long serialVersionUID=1L;

若是字段不想进行反序列化可以添加transcient 修饰。

属性:

private static final int DEFAULT_CAPACITY = 10;

private static final Object[] EMPTY_ELEMENTDATA = {};

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

transient Object[] elementData;

构造函数:
默认无参构造:可以看出当我们new ArrayList()时候,初始化并没有进行开辟空间存放元素,当添加元素是初始化容量为10 .

 public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

有参构造: 初始化容量大于 0 时,创建 Object 数组 ;  初始化容量等于 0 时,使用 EMPTY_ELEMENTDATA 对象

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

参数为集合,如果集合元素不是 Object[] 类型,则会创建新的 Object[] 数组,并将 elementData 赋值到其中,最后赋值给 elementData 

public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

最大数组长度:private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

新增元素 add :

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

grow() 扩容: 扩容至原数组长度的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);
    }

指定下标添加:

      public void add(int index, E element) {
//检查index 是否在数组范围内 rangeCheckForAdd(index); ensureCapacityInternal(size
+ 1); // Increments modCount!!

//将index +1 之后的元素向后挪一位copy赋值 System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; }

数组缩容:

public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size);
        }
    }

检测主动扩容:ensureCapacity  

 public void ensureCapacity(int minCapacity) {
        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
            // any size if not default element table
            ? 0
            // larger than default for default empty table. It's already
            // supposed to be at default size.
            : DEFAULT_CAPACITY;

        if (minCapacity > minExpand) {
            ensureExplicitCapacity(minCapacity);
        }
    }

添加集合元素:避免多次扩容 ,提高效率

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

移除元素:需要判断移除元素是否为null ,fastRemove() : size - index - 1 判断移除元素是否是最后一个;

elementData[--size] = null; // clear to let GC do its work 移除元素后将最后一位置为null 方便GC
public boolean remove(Object o) {
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }

private void fastRemove(int index) {
modCount++;
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
}

清除元素:clear ()  遍历将元素置为null   size=0

public void clear() {
        modCount++;

        // clear to let GC do its work
        for (int i = 0; i < size; i++)
            elementData[i] = null;

        size = 0;
    }

替换对应下标的元素: 

public E set(int index, E element) {
//检测下标是否超过列表size rangeCheck(index);      //将对应位置的元素替换 E oldValue
= elementData(index); elementData[index] = element; return oldValue; }

获取元素在列表中的下标:indexOf(),没有找到返回-1

public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

判断列表中是否包含元素:contains   实际上调用的是indexOf ()

public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }

克隆:调用supper.clone() 

 public Object clone() {
        try {
            ArrayList<?> v = (ArrayList<?>) super.clone();
            v.elementData = Arrays.copyOf(elementData, size);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            // this shouldn't happen, since we are Cloneable
            throw new InternalError(e);
        }
    }

转化为数组:toArray 返回的为Object 数组 因此我们在进行列表转数组的时候需要使用 toArray(T[] a)

 public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }

public <T> T[] toArray(T[] a) {
if (a.length < size)
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}

 阿里开发规范为:

 

创建 ArrayList 的子数组  subList(int fromIndex, int toIndex),返回原列表上的截取元素列表,返回值会随着原列表改变而改变

 public List<E> subList(int fromIndex, int toIndex) {
        subListRangeCheck(fromIndex, toIndex, size);
        return new SubList(this, 0, fromIndex, toIndex);
    }

 



 

posted @ 2021-05-16 15:15  山阴路的秋天  阅读(65)  评论(0编辑  收藏  举报