集合之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:
-
java.io.ObjectOutputStream:表示对象输出流 它是OutputStream类的一个子类,对应的ObjectOutputStream.WriteObject(Object object)就要求参数object实现Serializable接口。
-
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); }