list內部實現是一個名叫elementData的數組
1>list類的構造函數:
private transient Object[] elementData;//用來作爲一個緩衝數組
//帶初始化的構造函數,initialCapacity代表數組的初始容量
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
//根據用戶傳進initialCapacity初始化一個數組
this.elementData = new Object[initialCapacity];
}
/**
* Constructs an empty list with an initial capacity of ten.
*/
//如果用戶調用了不帶參數的構造函數,系統默認初始化大小爲10
public ArrayList() {
this(10);
}
//還有一個全局size,時刻記錄着元素的個數,代表着list的實際容量
private int size;
2>add(): 向列表的尾部添加指定的元素(可選操作)
public boolean add(E e) {
//ensureCapacity用來檢查如果數組中插入了這個值容量是否溢出,
ensureCapacity(size + 1); // Increments modCount!!
//在當前的位置插入元素,並把size+1;
elementData[size++] = e;
return true;
}
//注意這個檢查邊界的函數,後面的方法中差不多都會用到
public void ensureCapacity(int minCapacity) {
modCount++;
int oldCapacity = elementData.length;//xian把原來數組的長度存起來
if (minCapacity > oldCapacity) {//如果添加了元素之後,數組溢出,
Object oldData[] = elementData;//將原來數組的值存到另一個數組中
int newCapacity = (oldCapacity * 3)/2 + 1;//新開闢的空間在原來的基礎上擴大1.5倍+1
if (newCapacity < minCapacity)//如果新的容量還不能足夠的容納要添加的元素個數
newCapacity = minCapacity;//就把新容量定爲要添加的元素個數
// minCapacity is usually close to size, so this is a win:
//將elementData擴容後的數組返回給他自己,其中的內容不變,只是容量變大
//Arrays.copyOf函數做了好多事,最總調用的還是System.ArrayCopy(...)
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
3>add(int index, E element):制定的位置插入元素
/**
*
* @param index 要插入的位置
* @param element 要插入的元素
*/
public void add(int index, E element) {
//判斷用戶指定要插入的位置是否越界,或者非法
if (index > size || index < 0)
throw new IndexOutOfBoundsException(
"Index: "+index+", Size: "+size);
//檢查插入元素之後數組是否溢出
ensureCapacity(size+1); // Increments modCount!!
/*
* @param elementData 將要被拷貝的元素
* @param index 從那個位置開始拷貝
* @param elementData 拷貝到哪裏去(目標數組)
* @param index + 1 拷貝到目標數組的那個位置
* @param size - index 拷貝多少個元素
* 這個方法的作用 把用戶指定的位置的元素,一次向後移動一個單位
* 例如:
* elementData[1,2,4,5]現在要在下標爲2的位置插入3
* 這句這句話執行完的效果是是
* elementData[1,2,4,4,5] 可以看到45依次向後移動一個位置,新進來的元素直接覆蓋2後面的4
* 最終: elementData[1,2,3,4,5]
*
*/
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;//這句話就是覆蓋
size++;//元素個數+1
}
4>addAll(int index, Collection
/**
*
* @param c 要添加的集合
* @return
*/
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();//把集合轉換成數組,先存起來
int numNew = a.length;//numNew存的是集合的元素個數
//檢查元素插入這些集合元素後是否溢出,溢出擴容
ensureCapacity(size + numNew); // Increments modCount
//把 a數組元素從0開始的位置長度爲numNew個元素複製到elementData中size個位置,也就是默認追加到原來的元素之後
//list還有一個方法可以指定吧c集合添加到那個位置上,僅僅是把這裏的size值改變爲用戶指定的值即可
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
}
5>clear():從列表中移除所有元素
//很簡單,遍歷數組把元素清空就行,不要忘記了把size置0
public void clear() {
modCount++;
// Let gc do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
6>contains(Object o):如果列表包含指定的元素,則返回 true
/**
* 代碼也很簡單,只是要記得判斷null
* @param o 要判斷的元素
* @return
*/
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;
}
}
7>equals(Object o) :比較指定的對象與列表是否相等
/**
* @param Object o 要比較的內容
*/
public boolean equals(Object o) {
//如果要比交的是自己本身直接返回true,感慨大師寫的代碼是有多麼的嚴謹呀
if (o == this)
return true;
//如果要計較的對象不是list那還比較啥,直接返回false
if (!(o instanceof List))
return false;
//分別遍歷集合挨個比較,只要有一個不想等直接返回false
ListIterator<E> e1 = listIterator();
ListIterator e2 = ((List) o).listIterator();
while(e1.hasNext() && e2.hasNext()) {
E o1 = e1.next();
Object o2 = e2.next();
//如果o1 == null o2 == null 這個表達式爲true, 則整個if條件爲false,繼續while比較下一個
//如果o1!= null 執行o1.equals(o2) 爲真,則if條件爲假,繼續執行while
if (!(o1==null ? o2==null : o1.equals(o2)))
return false;
}
//當對象o1 或者對象o2任意一個遍歷到尾部時跳出while循環,這是隻能說明o1可能包含着o2
//比如說o1[1,2,3,4,5] o2[1,2,3,4],這樣的例子是完全符合的,只有o1和o2的元素完全相等,並且長度也相等時纔算真的相等
//那麼下面的這句就是用來比較長度是否相等的,我感覺是否可以先判斷長度,在判斷元素是否相等,這樣是否更有效的
//一己之見,可能本人眼拙 還未達到大師的水平
return !(e1.hasNext() || e2.hasNext());
}
8> E get(int index) :返回列表中指定位置的元素
比較簡單
/**
*
* @param index 要查找的元素下表
* @return
*/
public E get(int index) {
//檢查範圍
RangeCheck(index);
return (E) elementData[index];
}
/**
*
* @param index
*/
private void RangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(
"Index: "+index+", Size: "+size);
}
9>hashCode():返回列表的哈希碼值
原來hashcode是這樣產生的
public int hashCode() {
int hashCode = 1;
Iterator<E> i = iterator();
while (i.hasNext()) {
E obj = i.next();
hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
}
return hashCode;
}
10>indexOf(Object o):回此列表中第一次出現的指定元素的索引;如果此列表不包含該元素,則返回 -1。
參考前面的equals()方法
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;
}
11>isEmpty() : 如果列表不包含元素,則返回 true
好簡單,但是如果讓我們自己設計時,我們該怎樣設計呢
public boolean isEmpty() {
return size == 0;
}
12>lastIndexOf(Object o)
和indexOf()差不多,只是從頭開始
public int lastIndexOf(Object o) {
if (o == null) {
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)
return i;
} else {
for (int i = size-1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
13>remove(int index): 移除列表中指定位置的元素
檢查index值是否非法,size-1 刪除的元素之後的元素一次向前移動
public E remove(int index) {
RangeCheck(index);
modCount++;
E oldValue = (E) elementData[index];
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
return oldValue;
}
還有方法都差不多,這裏不再分析