前几天自我学习了ArrayList的源码,写了篇云笔记,现将其发布到博客,供大家学习交流,本人并非大神,如有任何问题,欢迎批评指正。
最初是看了这篇文章http://www.cnblogs.com/hzmark/archive/2012/12/20/ArrayList.html,不过是基于jdk1.6的,遂自己分析源码并写下此文,在此表示感谢。转载请注明出处,谢谢,http://blog.csdn.net/u010887744/article/details/49496093。
接口 |
特性 |
实现类 |
实现类特性 |
成员要求 |
List |
线性、有序的存储容器,可通过索引访问元素 |
ArrayList |
数组实现,非同步。 |
|
Vector |
类似ArrayList,同步。 |
|
||
LinkedList |
双向链表,非同步。 |
|
AbstractList提供了List接口的默认实现(个别方法为抽象方法)。
List接口(extends Collection)定义了列表必须实现的方法。
RandomAccess是一个标记接口,接口内没有定义任何内容。
实现了Cloneable接口的类,可以调用Object.clone方法返回该对象的浅拷贝。
通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。序列化接口没有方法或字段,仅用于标识可序列化的语义。
private static final long serialVersionUID = 8683452581122892189L; private static final int DEFAULT_CAPACITY = 10; // 容纳能力 private static final Object[] EMPTY_ELEMENTDATA = {}; private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; transient Object[] elementData; //non-private to simplify nested class access private int size; //实际包含元素的个数 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; private static final int MAX_ARRAY_SIZE = 2147483639; //反编译的源码是这个,why?? |
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; publicclass TestTransient { public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException { A a = new A(25, "张三"); System.out.println(a); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("d://mm.txt")); oos.writeObject(a); oos.close(); ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d://mm.txt")); a = (A) ois.readObject(); System.out.println(a); } } classAimplements Serializable { inta; transient String b; public A(inta, String b) { this.a = a; this.b = b; } public String toString() { return"a = " + a + ",b = " + b; } }
public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { thrownew IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } }
/** * Constructs an empty list with an initial capacity of ten. */ public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; //容量为10 }
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; } }
public static <T,U> T[] copyOf(U[] original, intnewLength, Class<? extends T[]> newType) { @SuppressWarnings("unchecked") T[] copy = ((Object)newType == (Object)Object[].class) ?(T[]) new Object[newLength] : (T[]) Array.newInstance(newType.getComponentType(), newLength); System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); //System.arraycopy详见add(int index, E element)方法 return copy; }
1
|
boolean add(E e) |
|
2
|
void
ensureCapacity(
int
minCapacity
)
|
|
3
|
void
add(
int
index
, E
element
)
|
|
4
|
boolean
addAll(Collection<?
extends
E>
c
)
|
|
5
|
boolean
addAll(
int
index
, Collection<?
extends
E>
c
)
|
|
6
|
E get(
int
index
)
|
|
7
|
Class<?> getClass()
|
|
8
|
void
clear()
|
|
9
|
void
trimToSize()
|
|
10
|
boolean
contains(Object
o
)
|
|
11
|
int
indexOf(Object
o
)
|
|
12
|
int
lastIndexOf(Object
o
)
|
|
13 |
boolean
containsAll(Collection collection)
|
AbstractCollection
|
14
|
int
hashCode()
|
java.util.
AbstractList
|
15
|
Object clone()
|
|
16
|
boolean
equals(Object
o
)
|
java.util.AbstractList
|
17
|
boolean
remove(Object
o
)
|
|
18
|
E remove(int index)
|
|
19
|
protected
void
removeRange(
int
fromIndex
,
int
toIndex
)
|
|
20
|
boolean removeAll(Collection <?> c)
|
|
21
|
boolean retainAll (Collection<?> c)
|
|
22
|
E set (int index , E element)
|
|
23
|
Object[] toArray()
|
|
24
|
<T> T[] toArray(T[] a) |
|
25
|
void sort(Comparator<? super E> c)
|
|
26
|
int size()
|
|
27
|
List<E> subList(int fromIndex , int toIndex)
|
|
1)、add(E e)方法:
public boolean add(E e) { // jdk1.6是ensureCapacity(size + 1) ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }调用 ensureCapacityInternal至少将elementData的容量增加了1,所以 elementData[size]不会出现越界的情况。
private void ensureCapacityInternal(int minCapacity) { //确保内部容量 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); }
private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) // 超出了数组可容纳的长度,则进行动态扩展 //个人理解:elementData每次扩展为1.5倍,当minCapacity达到临界值,上式if成立 grow(minCapacity); }
<span style="font-family: Consolas;"></span><pre name="code" class="java" style="font-size: 15px; line-height: 21px;"><span style="font-family: Consolas; background-color: rgb(255, 255, 51);"><strong>动态扩展核心</strong></span>
<pre name="code" class="java">private void grow(int minCapacity) { // 动态扩展核心 // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1);//1.5倍(15 >> 1=7) // 再次判断新数组的容量够不够 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); } private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow 溢出,貌似不可能有这种情况吧?? throw new OutOfMemoryError(); // 也就是说minCapacity在超出最大限制时允许达到Integer.MAX_VALUE, // 而不仅仅是Integer.MAX_VALUE-8 return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
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); // 具体实现见1)add方法。 } }elementData的length要么为0,要么>=10。
public void add(intindex, E element) { rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index+1, size-index); elementData[index] = element; size++; }
在指定位置插入指定元素。将当前处于该位置的元素(如果有的话)和所有后续元素向后移动(其索引加 1)。
/** * A version of rangeCheck used by add and addAll. */ private void rangeCheckForAdd(intindex) { if (index > size || index < 0) thrownew IndexOutOfBoundsException(outOfBoundsMsg(index)); }
// java.lang.System public static native void arraycopy(Object src, int srcPos, Object dest, intdestPos, intlength); // src 原数组,srcPos原数组开始位置 // dest目标数组,destPos目标数组开始位置 // length:the number of array elements to be copied.即要复制的数组元素的数目
public boolean addAll(Collection<? extends E> c) { Object[] a = c.toArray(); // 把c转化为数组a intnumNew = a.length; ensureCapacityInternal(size + numNew); // Increments modCount System.arraycopy(a, 0, elementData, size, numNew); size += numNew; return numNew != 0; }
插入集合c(以下函数上面已经细讲了,这里只讲流程了)
①将c转换为数组a;
public boolean addAll(intindex, Collection<? extends E> c) { rangeCheckForAdd(index); //检查索引合法性 Object[] a = c.toArray(); intnumNew = a.length; ensureCapacityInternal(size + numNew); // Increments modCount intnumMoved = size - index; if (numMoved > 0) System.arraycopy(elementData, index, elementData, index + numNew, numMoved); System.arraycopy(a, 0, elementData, index, numNew); size += numNew; returnnumNew != 0; }
在指定位置插入集合c
public E get(int index) { rangeCheck(index); return elementData(index); } |
private void rangeCheck(int index) { if (index >= size) thrownew IndexOutOfBoundsException(outOfBoundsMsg(index)); } |
// 调用java.lang.Object的getClass
/*
*@return The {@code Class} object that represents the runtime
* class of this object.
*/
public final native Class<?> getClass(); |
public void clear() { modCount++; // 从结构上修改此列表的次数加1 // clear to let GC do its work for (inti = 0; i < size; i++) elementData[i] = null; size = 0; }
清空Arraylist
9)trimToSize()
public void trimToSize() { modCount++; if (size < elementData.length) { elementData = (size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size); } }
// package java.util; @SuppressWarnings("unchecked") publicstatic <T> T[] copyOf(T[] original, intnewLength) { return (T[]) copyOf(original, newLength, original.getClass()); }
public static <T,U> T[] copyOf(U[] original, intnewLength, Class<? extends T[]> newType) { @SuppressWarnings("unchecked") T[] copy = ((Object)newType == (Object)Object[].class) ? (T[]) new Object[newLength] : (T[]) Array.newInstance(newType.getComponentType(), newLength); System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); returncopy; }去掉预留元素的位置。
public boolean contains(Object o) { return indexOf(o) >= 0; }判断对象o是否包含在Arraylist中。
注:不建议使用 contains(Object o)方法,看源码就知道了,调用其内置的indexOf方法,for循环一个个equals,这效率只能呵呵哒了,建议使用hashcode。
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; }
public int lastIndexOf(Object o) { if (o == null) { for (inti = size-1; i >= 0; i--) if (elementData[i]==null) returni; } else { for (inti = size-1; i >= 0; i--) if (o.equals(elementData[i])) returni; } return -1; }
public static void main(String[] args) { ArrayList arrayList = new ArrayList(); arrayList.add(1); arrayList.add(1); arrayList.add(null); arrayList.add(null); System.out.println(arrayList.contains(null)); System.out.println(arrayList.size()); }
输出: true 4原来Arraylist不仅 可以添加null ,而且可以“随意”加!
// 调用java.util.AbstractCollection的containsAll public boolean containsAll(Collection<?> c) { // ArrayList没有此方法 for (Object e : c) if (!contains(e)) return false; return true; }
public boolean contains(Object o) { // ArrayList的方法 return indexOf(o) >= 0; // 调用11的indexOf方法 }
// 再对比看一下package org.apache.commons.collections的containsAll public boolean containsAll(Collection collection) { if(fast) return list.containsAll(collection); ArrayList arraylist = list; JVM INSTR monitorenter ; return list.containsAll(collection); Exception exception; exception; throw exception; } //这块源码,表示看不懂。求大神讲解
// java.util.AbstractList public int hashCode() { inthashCode = 1; for (E e : this) hashCode = 31*hashCode + (e==null ? 0 : e.hashCode()); returnhashCode; }继承 java.util. AbstractList的hashCode 。
15)Object clone()
/** * Returns a shallow copy of this <tt>ArrayList</tt> instance. (The * elements themselves are not copied.) * @return a clone of this <tt>ArrayList</tt> instance */ public Object clone() { try { ArrayList<?> v = (ArrayList<?>) super.clone(); v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0; returnv; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable thrownew InternalError(e); } }
返回ArrayList实例的 浅拷贝 ,
public static void main(String[] args) { ArrayList List1 = new ArrayList(); List1.add(1); ArrayList List2 = (ArrayList) List1.clone(); System.out.println("未修改值(==)\t" + (List1 == List2)); System.out.println("未修改值(equals)\t" + List1.equals(List2)); List2.set(0, 2); System.out.println("list2--" + List2.hashCode() + "--" + List2.get(0)); System.out.println("list1--" + List1.hashCode() + "--" + List1.get(0)); }
未修改值(==) false 未修改值(equals) true list2--33--2 list1--32--1==输出为false,修改list2但list1未修改,这貌似是deepCopy啊????
浅拷贝(影子克隆):只复制基本类型。
深拷贝(深度克隆):基本类+对象。
16)boolean equals(Object o)
// java.util.AbstractList public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof List)) return false; ListIterator<E> e1 = listIterator(); ListIterator<?> e2 = ((List<?>) o).listIterator(); while (e1.hasNext() && e2.hasNext()) { E o1 = e1.next(); Object o2 = e2.next(); if (!(o1==null ? o2==null : o1.equals(o2))) return false; } return !(e1.hasNext() || e2.hasNext()); }先看一下 instanceof ,这是Java的一个关键字,一个二元操作符。作用是测试它左边的对象是否是它右边的类的实例,返回boolean类型的数据。详细见Java目录另一篇笔记《Java中的instanceof关键字》。
17)boolean remove(Object o)
public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); returntrue; } } else { for (intindex = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); returntrue; } } returnfalse; } /* * Private remove method that skips bounds checking and does not * return the value removed. */ privatevoidfastRemove(intindex) { modCount++; intnumMoved = size - index - 1; // 要移动的元素个数 if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work // 将最后一位赋值为null以便垃圾回收,GC(Garbage Collection) }首先判断要remove的元素是null还是非null,然后for循环查找,核心是fastRemove(index)方法。
elementData[--size] = null;因为arraycopy方法是将elementData的index+1处开始的元素往前复制,也就是说最后一个数本该消除,但还在那里,所以需要置空。如原数组{1,2,3,4},删除index=1时,首先调用arraycopy,结果为{1,3,4,4},最后一个4并没有删除。
public E remove(int index) { rangeCheck(index); // 检查索引合法性,详见get方法 modCount++; E oldValue = elementData(index); intnumMoved = size - index - 1; // 要移动的元素个数 if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work returnoldValue; }
删除指定位置的元素,调用的arraycopy方法前面已经讲过了。
protected void removeRange(intfromIndex, inttoIndex) { modCount++; intnumMoved = size - toIndex; System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved); // clear to let GC do its work intnewSize = size - (toIndex-fromIndex); for (inti = newSize; i < size; i++) { elementData[i] = null; } size = newSize; }
** * Removes from this list all of its elements that are contained in the * specified collection. */ public boolean removeAll(Collection<?> c) { Objects.requireNonNull(c); return batchRemove(c, false); }
/** * Retains only the elements in this list that are contained in the * specified collection. In other words, removes from this list all * of its elements that are not contained in the specified collection. */ public boolean retainAll(Collection<?> c) { Objects.requireNonNull(c); return batchRemove(c, true); }
// java.util.object publicstatic <T> T requireNonNull(T obj) { if (obj == null) thrownew NullPointerException(); returnobj; }
private boolean batchRemove(Collection<?> c, booleancomplement) { final Object[] elementData = this.elementData; intr = 0, w = 0; // w是重新存元素时的索引,r是原来的索引 booleanmodified = false; try { for (; r < size; r++) if (c.contains(elementData[r]) == complement) elementData[w++] = elementData[r]; } finally { // Preserve behavioral compatibility with AbstractCollection, // even if c.contains() throws. if (r != size) { System.arraycopy(elementData, r, elementData, w, size - r); w += size - r; } if (w != size) { // clear to let GC do its work for (inti = w; i < size; i++) elementData[i] = null; modCount += size - w; size = w; modified = true; } } returnmodified; }
public static void main(String[] args) { ArrayList List1 = new ArrayList(); ArrayList List2 = new ArrayList(); List1.add(1); List1.add(2); List1.add(3); List2.add(4); System.out.println(List1.removeAll(List2)); for (Object object : List1) { System.out.println(object); } }
false 1 2 3
public E set(intindex, E element) { rangeCheck(index); E oldValue = elementData(index); elementData[index] = element; returnoldValue; }
public Object[] toArray() { return Arrays.copyOf(elementData, size); } |
public Object[] toArray() { return Arrays.copyOf(elementData, size); } |
@SuppressWarnings("unchecked") publicstatic <T> T[] copyOf(T[] original, intnewLength) { return (T[]) copyOf(original, newLength, original.getClass()); } // copyOf方法详见ArrayList的第三个构造方法 |
@SuppressWarnings("unchecked") 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; }①如果传入数组的长度length小于size,返回一个新的数组,大小为size,类型与传入数组相同;
@Override @SuppressWarnings("unchecked") publicvoid sort(Comparator<? super E> c) { final int expectedModCount = modCount; Arrays.sort((E[]) elementData, 0, size, c); if (modCount != expectedModCount) { thrownew ConcurrentModificationException(); } modCount++; }
// Arrays.sort,一直在用 Arrays.sort(arr),总算看到他兄弟的真面目了 /* @param<T> the class of the objects to be sorted * @param a the array to be sorted * @param fromIndex the index of the first element (inclusive) to be sorted * @param toIndex the index of the last element (exclusive) to be sorted * @param c the comparator to determine the order of the array. A * {@code null} value indicates that the elements' * {@linkplain Comparable natural ordering} should be used. */ public static <T> void sort(T[] a, int fromIndex, int toIndex, Comparator<? super T> c) { if (c == null) { sort(a, fromIndex, toIndex); } else { rangeCheck(a.length, fromIndex, toIndex); if (LegacyMergeSort.userRequested) legacyMergeSort(a, fromIndex, toIndex, c); else TimSort.sort(a, fromIndex, toIndex, c, null, 0, 0); //暂不分析 } }
// Array的sort方法 public static void sort(Object[] a, intfromIndex, inttoIndex) { rangeCheck(a.length, fromIndex, toIndex); // 检查参数合法性 if (LegacyMergeSort.userRequested) legacyMergeSort(a, fromIndex, toIndex); else ComparableTimSort.sort(a, fromIndex, toIndex, null, 0, 0); }
// Array 的 rangeCheck方法 private static void rangeCheck(intarrayLength, intfromIndex, inttoIndex) { if (fromIndex > toIndex) { thrownew IllegalArgumentException( "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")"); } if (fromIndex < 0) { thrownew ArrayIndexOutOfBoundsException(fromIndex); } if (toIndex > arrayLength) { thrownew ArrayIndexOutOfBoundsException(toIndex); } }
// 这个表示看不懂 static final class LegacyMergeSort { privatestaticfinalbooleanuserRequested = java.security.AccessController.doPrivileged( new sun.security.action.GetBooleanAction( "java.util.Arrays.useLegacyMergeSort")).booleanValue(); }
/** To be removed in a future release. */ privatestatic <T> void legacyMergeSort(T[] a, intfromIndex, inttoIndex, Comparator<? super T> c) { T[] aux = copyOfRange(a, fromIndex, toIndex); if (c==null) mergeSort(aux, a, fromIndex, toIndex, -fromIndex); else mergeSort(aux, a, fromIndex, toIndex, -fromIndex, c); }
// Array的copyRange方法 @SuppressWarnings("unchecked") publics tatic <T> T[] copyOfRange(T[] original, intfrom, intto) { return copyOfRange(original, from, to, (Class<? extends T[]>) original.getClass()); } public static <T,U> T[] copyOfRange(U[] original, intfrom, intto, Class<? extendsT[]> newType) { intnewLength = to - from; if (newLength < 0) thrownew IllegalArgumentException(from + " > " + to); @SuppressWarnings("unchecked") T[] copy = ((Object)newType == (Object)Object[].class) ? (T[]) new Object[newLength] : (T[]) Array.newInstance(newType.getComponentType(), newLength); System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength)); returncopy; }
// Array 的 mergeSort 方法 /** * Src is the source array that starts at index 0 * Dest is the (possibly larger) array destination with a possible offset * low is the index in dest to start sorting * high is the end index in dest to end sorting * off is the offset into src corresponding to low in dest //何用????? * To be removed in a future release. */ @SuppressWarnings({"rawtypes", "unchecked"}) private static void mergeSort(Object[] src, Object[] dest, intlow, inthigh, intoff, Comparator c) { //off即传来的-fromIndex intlength = high - low; // Insertion sort on smallest arrays if (length < INSERTIONSORT_THRESHOLD) { for (inti=low; i<high; i++) //没有比较器c时,代码为 //for (intj=i; j>low && ((Comparable) dest[j-1]).compareTo(dest[j])>0; j--) for (intj=i; j>low && c.compare(dest[j-1], dest[j])>0; j--) swap(dest, j, j-1); // 源码这里新建了临时变量 Object t return; } // Recursively sort halves of dest into src intdestLow = low; intdestHigh = high; low += off; high += off; intmid = (low + high) >>> 1; // mergeSort(dest, src, low, mid, -off, c); mergeSort(dest, src, mid, high, -off, c); // If list is already sorted, just copy from src to dest. This is an // optimization that results in faster sorts for nearly ordered lists. // 没有比较器c时,代码为 // if (((Comparable)src[mid-1]).compareTo(src[mid]) <= 0) if (c.compare(src[mid-1], src[mid]) <= 0) { System.arraycopy(src, low, dest, destLow, length); return; } // Merge sorted halves (now in src) into dest for(inti = destLow, p = low, q = mid; i < destHigh; i++) { //没有比较器时,为 && ((Comparable)src[p]).compareTo(src[q])<=0 if (q >= high || p < mid && c.compare(src[p], src[q]) <= 0) dest[i] = src[p++]; else dest[i] = src[q++]; } }26)int size()
这个方法有陷阱,详情及破解方法见另一篇笔记《 java.util.List.SubList陷阱及解决方法 》。