System.Collections.ArrayList類是一個特殊的數組。通過添加和刪除元素,就可以動態改變數組的長度。
一.優點
1. 支持自動改變大小的功能
2. 可以靈活的插入元素
3. 可以靈活的刪除元素
二.局限性
跟一般的數組比起來,速度上差些
三.添加元素
1. publicvirtualintAdd(objectvalue);
將對象添加到ArrayList的結尾處
ArrayList aList = new ArrayList();aList.Add("a");aList.Add("b");aList.Add("c");aList.Add("d");aList.Add("e");內容為
abcde
2. publicvirtualvoidInsert(intindex,objectvalue);
將元素插入ArrayList的指定索引處
ArrayList aList = new ArrayList();aList.Add("a");aList.Add("b");aList.Add("c");aList.Add("d");aList.Add("e");aList.Insert(0,"aa");結果為
aaabcde
3. publicvirtualvoidInsertRange(intindex,ICollectionc);
將集合中的某個元素插入ArrayList的指定索引處
ArrayList aList = new ArrayList();aList.Add("a");aList.Add("b");aList.Add("c");aList.Add("d");aList.Add("e");ArrayList list2 = newArrayList();list2.Add("tt");list2.Add("ttt");aList.InsertRange(2,list2);結果為
abtttttcde
四.刪除
1. publicvirtualvoidRemove(objectobj);
從ArrayList中移除特定對象的第一個匹配項,注意是第一個
ArrayList aList = new ArrayList();aList.Add("a");aList.Add("b");aList.Add("c");aList.Add("d");aList.Add("e");aList.Remove("a");結果為
bcde
2. publicvirtualvoidRemoveAt(intindex);
移除ArrayList的指定索引處的元素
aList.Add("a");aList.Add("b");aList.Add("c");aList.Add("d");aList.Add("e");aList.RemoveAt(0);結果為
bcde
3. publicvirtualvoidRemoveRange(intindex,intcount);
從ArrayList中移除一定範圍的元素。 Index表示索引,count表示從索引處開始的數目
aList.Add("a");aList.Add("b");aList.Add("c");aList.Add("d");aList.Add("e");aList.RemoveRange(1,3);結果為
複製代碼代碼如下:ae
4. publicvirtualvoidClear();
從ArrayList中移除所有元素。
五.排序
1.publicvirtualvoidSort();
對ArrayList或它的一部分中的元素進行排序。
ArrayListaList=newArrayList();aList.Add("e");aList.Add("a");aList.Add("b");aList.Add("c");aList.Add("d");DropDownList1.DataSource=aList;//DropDownListDropDownList1;DropDownList1.DataBind();結果為
eabcd
ArrayListaList=newArrayList();aList.Add("a");aList.Add("b");aList.Add("c");aList.Add("d");aList.Add("e");aList.Sort();//排序DropDownList1.DataSource=aList;//DropDownListDropDownList1;DropDownList1.DataBind();結果為
abcde
2.publicvirtualvoidReverse();
將ArrayList或它的一部分中元素的順序反轉。
ArrayListaList=newArrayList();aList.Add("a");aList.Add("b");aList.Add("c");aList.Add("d");aList.Add("e");aList.Reverse();//反轉DropDownList1.DataSource=aList;//DropDownListDropDownList1;DropDownList1.DataBind();結果為
edcba
六.查找
1.publicvirtualintIndexOf(object);
2.publicvirtualintIndexOf(object,int);
3.publicvirtualintIndexOf(object,int,int);
返回ArrayList或它的一部分中某個值的第一個匹配項的從零開始的索引。沒找到返回-1。
ArrayList aList = new ArrayList(); aList.Add("a"); aList.Add("b"); aList.Add("c"); aList.Add("d"); aList.Add("e"); intnIndex=aList.IndexOf(“a”);//1 nIndex=aList.IndexOf(“p”);//沒找到,-1 4.publicvirtualintLastIndexOf(object);
5.publicvirtualintLastIndexOf(object,int);
6.publicvirtualintLastIndexOf(object,int,int);
返回ArrayList或它的一部分中某個值的最後一個匹配項的從零開始的索引。
ArrayList aList = new ArrayList(); aList.Add("a"); aList.Add("b"); aList.Add("a");//同0 aList.Add("d"); aList.Add("e"); intnIndex=aList.LastIndexOf("a");//值為2而不是0 7.publicvirtualboolContains(objectitem);
確定某個元素是否在ArrayList中。包含返回true,否則返回false
七.其他
1. publicvirtualintCapacity{get;set;}
獲取或設置ArrayList可包含的元素數。
2. publicvirtualintCount{get;}
獲取ArrayList中實際包含的元素數。
Capacity是ArrayList可以存儲的元素數。 Count是ArrayList中實際包含的元素數。 Capacity總是大於或等於Count。如果在添加元素時,Count超過Capacity,則該列表的容量會通過自動重新分配內部數組加倍。
如果Capacity的值顯式設置,則內部數組也需要重新分配以容納指定的容量。如果Capacity被顯式設置為0,則公共語言運行庫將其設置為默認容量。默認容量為16。
在調用Clear後,Count為0,而此時Capacity切是默認容量16,而不是0
3. publicvirtualvoidTrimToSize();
將容量設置為ArrayList中元素的實際數量。
如果不向列表中添加新元素,則此方法可用於最小化列表的內存系統開銷。
若要完全清除列表中的所有元素,請在調用TrimToSize之前調用Clear方法。截去空ArrayList會將ArrayList的容量設置為默認容量,而不是零。
ArrayList aList = new ArrayList();aList.Add("a");aList.Add("b");aList.Add("c");aList.Add("d");aList.Add("e");//Count=5,Capacity=16,aList.TrimToSize();//Count=Capacity=5;八.源碼分析
List 接口的一個實現類,內部是用一個數組存儲元素值,相當於一個可變大小的數組。
1.簽名
public class ArrayList<E>extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, Serializable
可以看到ArrayList繼承了AbstractList抽像類,它實現了List接口的大多數方法。如果要實現一個不可變的List,只要繼承這個類並且實現get(int)和size方法。如果要實現可變的List,需要覆蓋set(int, E)。另外,如果List的大小是可變的,還要覆蓋add(int, E)和remove()方法。
2.構造器
ArrayList提供了三個構造器:
ArrayList()ArrayList(Collection<? extends E> c)ArrayList(int initialCapacity)
Collection接口約定,每個集合類應該提供兩個”標準”構造器,一個是無參數的構造器(上面第一個),另外一個是擁有單個參數(類型為Collettion)的構造器(上面第二個)。 ArrayList還提供了第三個構造器,其接受一個int值,用於設置ArrayLi的初始大小(默認大小為10)。
3.相關方法
trimToSizepublic void trimToSize() { modCount++; int oldCapacity = elementData.length; if (size < oldCapacity) { elementData = Arrays.copyOf(elementData, size); } }用於把ArrayList的容量縮減到當前實際大小,減少存儲容量。其中的變量modCount由AbstracList繼承而來,記錄List發生結構化修改(structurally modified)的次數。 elementData中實際存儲了ArrayList的元素,在ArrayList中聲明為:private transient Object[] elementData;變量size是ArrayList的元素數量,當size < oldCapacity時,調用Arrays.copyOf方法實現縮減。
4.indexOf 和lasIndexOf
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; }這兩個方法返回指定元素的下標,要區分參數是否為null。 lastIndexOf和indexOf類似,只不過是從後往前搜索。
5.ensureCapacity
public void ensureCapacity(int minCapacity) { if (minCapacity > 0) ensureCapacityInternal(minCapacity); }private void ensureCapacityInternal(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); }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); }這個方法可以確保ArrayList的大小
6.add 和addAll
public void add(int index, E element) { rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } add(int index, E element)向指定位置添加元素,首先調用rangeCheckForAdd檢查index是否有效,如果index > size || index < 0將拋出異常。然後確保容量加1,調用System.arraycopy把從index開始的元素往後移動一個位置。最後把index處的值設置為添加的元素。還有一個重載的add(E e)方法是直接把元素添加到末尾。
addAll(Collection<? extends E> c)和addAll(int index, Collection<? extends E> c)則分別是向末尾和指定位置添加Collection中的所有元素。
7.remove 和removeAll
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; }remove(Object o)方法刪除指定的元素。首先是查找元素位置,然後調用fastRemove(index)刪除,其代碼如下:
private void fastRemove(int index) { modCount++; int numMoved = size - index - 1; if (numMoved > 0) //把index+1往後的元素都往前移動一個位置System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // Let gc do its work }重載的remove(int index)方法用於刪除指定位置的元素。 removeRange(int fromIndex, int toIndex)用於刪除指定位置之間的所有元素。
removeAll(Collection<?> c)和retainAll(Collection<?> c)代碼如下:
public boolean removeAll(Collection<?> c) { Objects.requireNonNull(c); return batchRemove(c, false); }public boolean retainAll(Collection<?> c) { Objects.requireNonNull(c); return batchRemove(c, true); }它們都是通過調用batchRemove方法實現的,其代碼如下:
private boolean batchRemove(Collection<?> c, boolean complement) { final Object[] elementData = this.elementData; int r = 0, w = 0; boolean modified = 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 (int i = w; i < size; i++) elementData[i] = null; modCount += size - w; size = w; modified = true; } } return modified; }這個方法有兩個參數,第一個是操作的Collection,第二個是一個布爾值,通過設置為true或false來選擇是removeAll還是retainAll。 try裡面的語句是把留下來的放在0到w之間,然後在finally中第二個if處理w之後的空間,第一個是在c.contains()拋出異常時執行。