Android源码之ArrayList
来源:互联网 发布:控制台运行java程序 编辑:程序博客网 时间:2024/05/01 09:54
今天是上班后的第一天,由于项目正在测试阶段,比较空闲,所以研究了一下Android中的ArrayList源码,先说明本篇文章是基于android-23进行的分析,因为我看到网上很多的arrayList源码和我看到的android源码不一样。
首先我们看下Java集合框架中的继承图。
由于今天主要讲的是ArrayList,以后的类我会在以后一一分析。那现在就开始我们今天的源码阅读。
1:我们都知道arraylist是基于数组实现的,是一个动态的数组,其容量能够自动的增长,
2:ArrayList不是线程安全的,只能用在单线程环境下,多线程环境下可以考Collections.synchronizedList(List l)函数返回一个线程安全的ArrayList类,也可以使用concurrent并发包下的CopyOnWriteArrayList类。
3:ArrayList实现了Serializable接口,因此它支持序列化,能够通过序列化传送,实现了RandowAccess接口,支持快速随机访问,实现了Cloneable接口,能被克隆。
public class ArrayList<E> extends AbstractList<E> implements Cloneable, Serializable, RandomAccess { //默认的最小的增加数量 private static final int MIN_CAPACITY_INCREMENT = 12; //ArrayList中的个数 int size; //当前的数组 transient Object[] array; //初始化array,EmptyArray.OBJECT是长度为0的数组 public ArrayList(int capacity) { if (capacity < 0) { throw new IllegalArgumentException("capacity < 0: " + capacity); } array = (capacity == 0 ? EmptyArray.OBJECT : new Object[capacity]); } //EmptyArray.OBJECT是长度为0的数组 public ArrayList() { array = EmptyArray.OBJECT; } //初始化传进来的collection长度的数组 public ArrayList(Collection<? extends E> collection) { if (collection == null) { throw new NullPointerException("collection == null"); } Object[] a = collection.toArray(); if (a.getClass() != Object[].class) { Object[] newArray = new Object[a.length]; System.arraycopy(a, 0, newArray, 0, a.length); a = newArray; } array = a; size = a.length; } @Override public boolean add(E object) { Object[] a = array; int s = size; if (s == a.length) { //s小于6的话,设置newArray的长度为s+12,不然的话newArray的长度是1.5倍的s 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; } //添加对象到指定的位置 @Override public void add(int index, E object) { Object[] a = array; int s = size; if (index > s || index < 0) { throwIndexOutOfBoundsException(index, s); } //长度小于a的话,直接添加 if (s < a.length) { System.arraycopy(a, index, a, index + 1, s - index); } else { //长度大于a的话,又是编程原来的1.5倍 Object[] newArray = new Object[newCapacity(s)]; //index位置前面的copy System.arraycopy(a, 0, newArray, 0, index); //index位置后面的copy System.arraycopy(a, index, newArray, index + 1, s - index); array = a = newArray; } //赋值当前的index值为object a[index] = object; size = s + 1; modCount++; } //判断当前的数组长度,若小于6.则增长值为12,不然的话增长值为把数组的长度*2 private static int newCapacity(int currentCapacity) { int increment = (currentCapacity < (MIN_CAPACITY_INCREMENT / 2) ? MIN_CAPACITY_INCREMENT : currentCapacity >> 1); return currentCapacity + increment; } //添加一个集合到当前的集合中 @Override public boolean addAll(Collection<? extends E> collection) { Object[] newPart = collection.toArray(); int newPartSize = newPart.length; if (newPartSize == 0) { return false; } Object[] a = array; int s = size; int newSize = s + newPartSize; // If add overflows, arraycopy will fail if (newSize > a.length) { int newCapacity = newCapacity(newSize - 1); // ~33% growth room Object[] newArray = new Object[newCapacity]; System.arraycopy(a, 0, newArray, 0, s); array = a = newArray; } System.arraycopy(newPart, 0, a, s, newPartSize); size = newSize; modCount++; return true; } //添加集合到指定的位置 @Override public boolean addAll(int index, Collection<? extends E> collection) { int s = size; if (index > s || index < 0) { throwIndexOutOfBoundsException(index, s); } Object[] newPart = collection.toArray(); int newPartSize = newPart.length; if (newPartSize == 0) { return false; } Object[] a = array; int newSize = s + newPartSize; // If add overflows, arraycopy will fail if (newSize <= a.length) { System.arraycopy(a, index, a, index + newPartSize, s - index); } else { int newCapacity = newCapacity(newSize - 1); // ~33% growth room Object[] newArray = new Object[newCapacity]; System.arraycopy(a, 0, newArray, 0, index); System.arraycopy(a, index, newArray, index + newPartSize, s-index); array = a = newArray; } System.arraycopy(newPart, 0, a, index, newPartSize); size = newSize; modCount++; return true; } static IndexOutOfBoundsException throwIndexOutOfBoundsException(int index, int size) { throw new IndexOutOfBoundsException("Invalid index " + index + ", size is " + size); } //移除当前数组的内容,每个字都会编程null,然后设置size=0 @Override public void clear() { if (size != 0) { Arrays.fill(array, 0, size, null); size = 0; modCount++; } } @Override public Object clone() { try { ArrayList<?> result = (ArrayList<?>) super.clone(); result.array = array.clone(); return result; } catch (CloneNotSupportedException e) { throw new AssertionError(); } } //保证当前数组能够容纳 public void ensureCapacity(int minimumCapacity) { Object[] a = array; if (a.length < minimumCapacity) { Object[] newArray = new Object[minimumCapacity]; System.arraycopy(a, 0, newArray, 0, size); array = newArray; modCount++; } } @Override public E get(int index) { if (index >= size) { throwIndexOutOfBoundsException(index, size); } return (E) array[index]; } @Override public int size() { return size; } @Override public boolean isEmpty() { return size == 0; } @Override public boolean contains(Object object) { Object[] a = array; int s = size; if (object != null) { for (int i = 0; i < s; i++) { if (object.equals(a[i])) { return true; } } } else { for (int i = 0; i < s; i++) { if (a[i] == null) { return true; } } } return false; } @Override public int indexOf(Object object) { Object[] a = array; int s = size; if (object != null) { for (int i = 0; i < s; i++) { if (object.equals(a[i])) { return i; } } } else { for (int i = 0; i < s; i++) { if (a[i] == null) { return i; } } } return -1; } @Override public int lastIndexOf(Object object) { Object[] a = array; if (object != null) { for (int i = size - 1; i >= 0; i--) { if (object.equals(a[i])) { return i; } } } else { for (int i = size - 1; i >= 0; i--) { if (a[i] == null) { return i; } } } return -1; } @Override public E remove(int index) { Object[] a = array; int s = size; if (index >= s) { throwIndexOutOfBoundsException(index, s); } @SuppressWarnings("unchecked") E result = (E) a[index]; System.arraycopy(a, index + 1, a, index, --s - index); a[s] = null; // Prevent memory leak size = s; modCount++; return result; } @Override public boolean remove(Object object) { Object[] a = array; int s = size; if (object != null) { for (int i = 0; i < s; i++) { if (object.equals(a[i])) { System.arraycopy(a, i + 1, a, i, --s - i); a[s] = null; // Prevent memory leak size = s; modCount++; return true; } } } else { for (int i = 0; i < s; i++) { if (a[i] == null) { System.arraycopy(a, i + 1, a, i, --s - i); a[s] = null; // Prevent memory leak size = s; modCount++; return true; } } } return false; } @Override protected void removeRange(int fromIndex, int toIndex) { if (fromIndex == toIndex) { return; } Object[] a = array; int s = size; if (fromIndex >= s) { throw new IndexOutOfBoundsException("fromIndex " + fromIndex + " >= size " + size); } if (toIndex > s) { throw new IndexOutOfBoundsException("toIndex " + toIndex + " > size " + size); } if (fromIndex > toIndex) { throw new IndexOutOfBoundsException("fromIndex " + fromIndex + " > toIndex " + toIndex); } System.arraycopy(a, toIndex, a, fromIndex, s - toIndex); int rangeSize = toIndex - fromIndex; Arrays.fill(a, s - rangeSize, s, null); size = s - rangeSize; modCount++; } @Override public E set(int index, E object) { Object[] a = array; if (index >= size) { throwIndexOutOfBoundsException(index, size); } @SuppressWarnings("unchecked") E result = (E) a[index]; a[index] = object; return result; } @Override public Object[] toArray() { int s = size; Object[] result = new Object[s]; System.arraycopy(array, 0, result, 0, s); return result; } @Override public <T> T[] toArray(T[] contents) { int s = size; if (contents.length < s) { @SuppressWarnings("unchecked") T[] newArray = (T[]) Array.newInstance(contents.getClass().getComponentType(), s); contents = newArray; } System.arraycopy(this.array, 0, contents, 0, s); if (contents.length > s) { contents[s] = null; } return contents; } public void trimToSize() { int s = size; if (s == array.length) { return; } if (s == 0) { array = EmptyArray.OBJECT; } else { Object[] newArray = new Object[s]; System.arraycopy(array, 0, newArray, 0, s); array = newArray; } modCount++; } @Override public Iterator<E> iterator() { return new ArrayListIterator(); } private class ArrayListIterator implements Iterator<E> { /** Number of elements remaining in this iteration */ private int remaining = size; /** Index of element that remove() would remove, or -1 if no such elt */ private int removalIndex = -1; /** The expected modCount value */ private int expectedModCount = modCount; public boolean hasNext() { return remaining != 0; } @SuppressWarnings("unchecked") public E next() { ArrayList<E> ourList = ArrayList.this; int rem = remaining; if (ourList.modCount != expectedModCount) { throw new ConcurrentModificationException(); } if (rem == 0) { throw new NoSuchElementException(); } remaining = rem - 1; return (E) ourList.array[removalIndex = ourList.size - rem]; } public void remove() { Object[] a = array; int removalIdx = removalIndex; if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } if (removalIdx < 0) { throw new IllegalStateException(); } System.arraycopy(a, removalIdx + 1, a, removalIdx, remaining); a[--size] = null; // Prevent memory leak removalIndex = -1; expectedModCount = ++modCount; } } @Override public int hashCode() { Object[] a = array; int hashCode = 1; for (int i = 0, s = size; i < s; i++) { Object e = a[i]; hashCode = 31 * hashCode + (e == null ? 0 : e.hashCode()); } return hashCode; } @Override public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof List)) { return false; } List<?> that = (List<?>) o; int s = size; if (that.size() != s) { return false; } Object[] a = array; if (that instanceof RandomAccess) { for (int i = 0; i < s; i++) { Object eThis = a[i]; Object ethat = that.get(i); if (eThis == null ? ethat != null : !eThis.equals(ethat)) { return false; } } } else { // Argument list is not random access; use its iterator Iterator<?> it = that.iterator(); for (int i = 0; i < s; i++) { Object eThis = a[i]; Object eThat = it.next(); if (eThis == null ? eThat != null : !eThis.equals(eThat)) { return false; } } } return true; } private static final long serialVersionUID = 8683452581122892189L; 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(); } } }
1、注意其三个不同的构造方法。无参构造方法构造的ArrayList的容量默认为0,带有Collection参数的构造方法,将Collection转化为数组赋给ArrayList的实现。
2、注意扩充容量的方法ensureCapacity。ArrayList在每次增加元素(可能是1个,也可能是一组)时,都要调用该方法来确保足够的容量。当容量不足以容纳当前的元素个数时,就设置新的容量为旧的容量的1.5倍,如果设置后的新容量还不够,则直接新容量设置为传入的参数(也就是所需的容量),而后用Arrays.copyof()方法将元素拷贝到新的数组(详见下面的第3点)。从中可以看出,当容量不够时,每次增加元素,都要将原来的元素拷贝到一个新的数组中,非常之耗时,也因此建议在事先能确定元素数量的情况下,才使用ArrayList,否则建议使用LinkedList。
3、ArrayList的实现中大量地调用了Arrays.copyof()和System.arraycopy()方法。
看System.arraycopy()方法,该方法被标记了native,调用了系统的C/C++代码,在JDK中是看不到的,但在openJDK中可以看到其源码。该函数实际上最终调用了C语言的memmove()函数,因此它可以保证同一个数组内元素的正确复制和移动,比一般的复制方法的实现效率要高很多,很适合用来批量处理数组。Java强烈推荐在复制大量数组元素时用该方法,以取得更高的效率。
4、注意ArrayList的两个转化为静态数组的toArray方法。
第一个,Object[] toArray()方法。该方法有可能会抛出java.lang.ClassCastException异常,如果直接用向下转型的方法,将整个ArrayList集合转变为指定类型的Array数组,便会抛出该异常,而如果转化为Array数组时不向下转型,而是将每个元素向下转型,则不会抛出该异常,显然对数组中的元素一个个进行向下转型,效率不高,且不太方便。
第二个, T[] toArray(T[] a)方法。该方法可以直接将ArrayList转换得到的Array进行整体向下转型(转型其实是在该方法的源码中实现的),且从该方法的源码中可以看出,参数a的大小不足时,内部会调用Arrays.copyOf方法,该方法内部创建一个新的数组返回。
5、ArrayList基于数组实现,可以通过下标索引直接查找到指定位置的元素,因此查找效率高,但每次插入或删除元素,就要大量地移动元素,插入删除元素的效率低,建议使用LinkedList。
6、在查找给定元素索引值等的方法中,源码都将该元素的值分为null和不为null两种情况处理,ArrayList中允许元素为null。
- Android源码之ArrayList
- ArrayList(二): Android编程之ArrayList源码详解及使用
- 源码分析之ArrayList
- Java源码之ArrayList
- 源码分析之ArrayList
- 源码学习之ArrayList
- 源码阅读之ArrayList
- JAVA源码之ArrayList
- JDK8 源码之ArrayList
- java源码之Arraylist
- Java源码之ArrayList
- 源码解析之--ArrayList
- android源码解析 -- ArrayList
- Android编程之ArrayList源码详解及使用
- Android编程之ArrayList源码详解及使用
- Java源码之ArrayList(二)
- JDK源码学习之ArrayList
- java源码分析之ArrayList
- VS2010下建立MFC程序
- 使用camera、matrix仿即刻APP换一换
- 假期训练—— Repeating Decimals UVA - 202 模拟
- sed 脚本分隔符引起的问题 的问题
- 1021. Deepest Root (25)
- Android源码之ArrayList
- XXX
- Python的charts和Jupyter的使用 使数据可视化 对58同城的爬取
- Bootstrap学习笔记(五)菜单、按钮及导航
- 关于Spring容器的理解
- RecyclerView的用法
- spring data jpa
- php 使用ssh2 操作linux、mysql(模拟阿里云控制台)
- JDBCTemplate调用存储过程