JavaSE7 ArrayList源码 上
这是jre7版本的
public class ArrayList<E> extends AbstractList<E>//这个 extends AbstractCollection<E> implements List<E> implements List<E>, RandomAccess, Cloneable, Serializable { private static final long serialVersionUID = 8683452581122892189L; /** * 看下面这两个私有属性,就知道ArrayList实际上就是一个数组 * 其(数组、ArrayList)数据结构就是一个简单的线性序列 */ //数组elementData 存储ArrayList的所有数据 private transient Object[] elementData; //size<=elementData.length,两者没什么特别关系 //size是数组elementData中元素(E) 的个数 private int size; private static final int MAX_ARRAY_SIZE = 2147483639; /** * 构造方法1 * 可以初始化数组大小 * 例:ArrayList<E> array = new ArrayList<E>(10000); * 这时候size=0,但是数组的容量是10000 */ public ArrayList(int paramInt) { if (paramInt < 0) { throw new IllegalArgumentException("Illegal Capacity: " + paramInt); } this.elementData = new Object[paramInt]; } /** * 构造方法2 * 默认构造方法,初始化数组大小是10,感觉好小啊 */ public ArrayList() { //表示调用构造方法1 this(10); } /** * 构造方法3 * 可以放一个实现Collection接口的集合进去 */ public ArrayList(Collection<? extends E> paramCollection) { // 1.将集合转换成数组,elementData指向这个数组 this.elementData = paramCollection.toArray(); // 2.设置size值 this.size = this.elementData.length; // 3.判断ele..是不是Object数组,不是的话创建一个,将内容(基本类型的值,对象的引用)copy进新数组中,返回 if (this.elementData.getClass() != [Ljava.lang.Object.class) { this.elementData = Arrays.copyOf(this.elementData, this.size, [Ljava.lang.Object.class); } }
???
?
?下面看一下,构造方法3中的第一步(假设传进来的是一个ArrayList)和第三步。
/** * ArrayList实现的 Collection接口中toArray()方法 */ public Object[] toArray() { return Arrays.copyOf(this.elementData, this.size); } /** * 在Arrays类中找到的copyOf的方法 */ public static <T> T[] copyOf(T[] paramArrayOfT, int paramInt) { return (Object[])copyOf(paramArrayOfT, paramInt, paramArrayOfT.getClass()); } /** * 直接看这个吧,上面构造方法3的第三步调用的也是这个方法 */ public static <T, U> T[] copyOf(U[] paramArrayOfU, int paramInt, Class<? extends T[]> paramClass) { //根据给定的paramClass数组类型,生成一个大小paramInt的新数组 Object[] arrayOfObject = //三目运算 paramClass == [Ljava.lang.Object.class ? //构造方法3的第三步走的这里 (Object[])new Object[paramInt] : //Array.newInstance 是native的,看不到了 (Object[])Array.newInstance(paramClass.getComponentType(), paramInt); //这个也是 native方法,x = Math.min(paramArrayOfU.length, paramInt) //复制paramArrayOfU[0~x]内容到arrayOfObjec[0~x]中,用这个操作数组还是很爽的 System.arraycopy(paramArrayOfU, 0, arrayOfObject, 0, Math.min(paramArrayOfU.length, paramInt)); return arrayOfObject; }
?
?
??其实一般的构造方法3,第三步都会走。
ArrayList<String> array = new ArrayList<String>(Arrays.asList("a","b")); //对应构造方法3的第一步 Object[] elementData = Arrays.asList("a","b").toArray(); System.err.println(elementData.getClass());//输出class [Ljava.lang.String;
??
?
下面继续源码:对数组进行扩容
/** * 给数组瘦身,释放资源,确定数组大小不会改变时用这个 * 生成一个新数组大小与元素个数一样 */ public void trimToSize() { //记录对arrayList的操作次数?不知道有什么用处 this.modCount += 1; int i = this.elementData.length; if (this.size < i) { //上面介绍过了 this.elementData = Arrays.copyOf(this.elementData, this.size); } } /** * 手动给数组扩容,生成一个容量不小于paramInt数组,然后将内容copy进去 */ public void ensureCapacity(int paramInt) { if (paramInt > 0) { ensureCapacityInternal(paramInt); } } /** * 给定数值不能比当前数组容量小。 */ private void ensureCapacityInternal(int paramInt) { this.modCount += 1; if (paramInt - this.elementData.length > 0) { grow(paramInt); } } /** * 执行扩容 */ private void grow(int paramInt) { int i = this.elementData.length; //自己会根据当前容量算出一个扩容值,跟给定值比较选择最大的 //移位操作符>> 参考:http://flyouwith.iteye.com/blog/2163032 int j = i + (i >> 1); if (j - paramInt < 0) { j = paramInt; } if (j - 2147483639 > 0) { //限定数组最大的容量不能超过多少 j = hugeCapacity(paramInt); } //继续copy this.elementData = Arrays.copyOf(this.elementData, j); } /** * 最大数值能不能超过Integer.MAX_VALUE * 2147483647 */ private static int hugeCapacity(int paramInt) { if (paramInt < 0) { throw new OutOfMemoryError(); } return paramInt > 2147483639 ? Integer.MAX_VALUE : 2147483639; }
?下面内容是一些基本方法
/** * 返回数组中元素个数 */ public int size() { return this.size; } /** * 是否只有一副皮囊 */ public boolean isEmpty() { return this.size == 0; } /** * 是否包含制定paramObject */ public boolean contains(Object paramObject) { return indexOf(paramObject) >= 0; } /** * paramObject 在数组中的一次出现的位置 * 通过对象的equals比较 */ public int indexOf(Object paramObject) { int i; if (paramObject == null) { for (i = 0; i < this.size; i++) { if (this.elementData[i] == null) { return i; } } } else { for (i = 0; i < this.size; i++) { if (paramObject.equals(this.elementData[i])) { return i; } } } return -1; } /** * paramObject 在数组中最后一次出现的位置 * 从后面开始循环 * 通过对象的equals比较 */ public int lastIndexOf(Object paramObject) { int i; if (paramObject == null) { for (i = this.size - 1; i >= 0; i--) { if (this.elementData[i] == null) { return i; } } } else { for (i = this.size - 1; i >= 0; i--) { if (paramObject.equals(this.elementData[i])) { return i; } } } return -1; } /** * 复制 * 数组存基本类型的值,对象的引用。 * 所以copy的不过是引用,都指向一个对象 */ public Object clone() { try { ArrayList localArrayList = (ArrayList)super.clone(); localArrayList.elementData = Arrays.copyOf(this.elementData, this.size); localArrayList.modCount = 0; return localArrayList; } catch (CloneNotSupportedException localCloneNotSupportedException) { throw new InternalError(); } } /** * 转换成数组,对象存引用 */ public Object[] toArray() { return Arrays.copyOf(this.elementData, this.size); } /** * 新建一个数组,放到这里拷贝ArrayList中内容 */ public <T> T[] toArray(T[] paramArrayOfT) { //如果给定数组容量小于size ,则生成一个大小是size的数组,然后把内容copy进去 if (paramArrayOfT.length < this.size) { return (Object[])Arrays.copyOf(this.elementData, this.size, paramArrayOfT.getClass()); } //否则直接copy,上面有介绍这个方法的含义 System.arraycopy(this.elementData, 0, paramArrayOfT, 0, this.size); if (paramArrayOfT.length > this.size) { paramArrayOfT[this.size] = null; } return paramArrayOfT; } /** * 返回数组指定位置的元素 */ E elementData(int paramInt) { return this.elementData[paramInt]; } /** * 返回指定位置的元素 */ public E get(int paramInt) { rangeCheck(paramInt);//检核是否越界 return elementData(paramInt); } /** * 替换指定位置的元素,返回被替换元素 */ public E set(int paramInt, E paramE) { rangeCheck(paramInt);//检核是否越界 Object localObject = elementData(paramInt); this.elementData[paramInt] = paramE; return localObject; } /** * 在末尾添加元素。 * 第一步上面有介绍这个方法。扩容 * 注意:size加1 */ public boolean add(E paramE) { ensureCapacityInternal(this.size + 1); this.elementData[(this.size++)] = paramE; return true; } /** * 指定位置添加元素,从指定位置开始后面元素统一后移一位 * 这里不是用的for循环来移位,而是copy,即使这样也比LinkedList慢好多 * 这个如果用for循环的话时间复杂度是O(this.size - paramInt) copy应该是比这小的 * 但是肯定比LinkedList 的O(1) 要大的多 * 注意:size加1 */ public void add(int paramInt, E paramE) { rangeCheckForAdd(paramInt);//检核是否越界 ensureCapacityInternal(this.size + 1); System.arraycopy(this.elementData, paramInt, this.elementData, paramInt + 1, this.size - paramInt); this.elementData[paramInt] = paramE; this.size += 1; } /** * 跟上面性质是一样的。把删除位置后面的元素统一向前移动一位 * 比LinkedList慢 * 注意:size减1 */ public E remove(int paramInt) { rangeCheck(paramInt);//检核是否越界 this.modCount += 1; Object localObject = elementData(paramInt); int i = this.size - paramInt - 1; if (i > 0) { System.arraycopy(this.elementData, paramInt + 1, this.elementData, paramInt, i); } this.elementData[(--this.size)] = null; return localObject; } /** * 删除对象,现查到对象在集合中的位置 * 比LinkedList慢 */ public boolean remove(Object paramObject) { int i; if (paramObject == null) { for (i = 0; i < this.size; i++) { if (this.elementData[i] == null) { fastRemove(i); return true; } } } else { for (i = 0; i < this.size; i++) { if (paramObject.equals(this.elementData[i])) { fastRemove(i); return true; } } } return false; } /** * 因为是在集合众找到的位置。所以不需要检核,直接删除 */ private void fastRemove(int paramInt) { this.modCount += 1; int i = this.size - paramInt - 1; if (i > 0) { System.arraycopy(this.elementData, paramInt + 1, this.elementData, paramInt, i); } this.elementData[(--this.size)] = null; } /** * 清空,通过for循环 */ public void clear() { this.modCount += 1; for (int i = 0; i < this.size; i++) { this.elementData[i] = null; } this.size = 0; } /** * 添加一个集合到当前集合后面 * 先把要添加的集合转变成数组,然后对this数组扩容,copy到this数组中 * 比LinkedList慢 */ public boolean addAll(Collection<? extends E> paramCollection) { Object[] arrayOfObject = paramCollection.toArray(); int i = arrayOfObject.length; ensureCapacityInternal(this.size + i); System.arraycopy(arrayOfObject, 0, this.elementData, this.size, i); this.size += i; return i != 0; } /** * 在指定位置插入集合, * 先将扩容,然后移位,之后把内容copy进来 * 比LinkedList慢 */ public boolean addAll(int paramInt, Collection<? extends E> paramCollection) { rangeCheckForAdd(paramInt);//检核是否越界 Object[] arrayOfObject = paramCollection.toArray(); int i = arrayOfObject.length; ensureCapacityInternal(this.size + i); int j = this.size - paramInt; if (j > 0) { System.arraycopy(this.elementData, paramInt, this.elementData, paramInt + i, j); } System.arraycopy(arrayOfObject, 0, this.elementData, paramInt, i); this.size += i; return i != 0; } /** * 这是protected的不能用。。 * remove区间的内容 * 先把paramInt2后的内容copy到paramInt1后面 * 然后把后面paramInt2-paramInt1位置的元素清空 */ protected void removeRange(int paramInt1, int paramInt2) { this.modCount += 1; int i = this.size - paramInt2; System.arraycopy(this.elementData, paramInt2, this.elementData, paramInt1, i); int j = this.size - (paramInt2 - paramInt1); while (this.size != j) { this.elementData[(--this.size)] = null; } } /** * 检核越界 */ private void rangeCheck(int paramInt) { if (paramInt >= this.size) { throw new IndexOutOfBoundsException(outOfBoundsMsg(paramInt)); } } /** * 检核越界 */ private void rangeCheckForAdd(int paramInt) { if ((paramInt > this.size) || (paramInt < 0)) { throw new IndexOutOfBoundsException(outOfBoundsMsg(paramInt)); } } /** * 异常信息 */ private String outOfBoundsMsg(int paramInt) { return "Index: " + paramInt + ", Size: " + this.size; }
??
?
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。