Java中ArrayList類(lèi)的用法與源碼完全解析
System.Collections.ArrayList類(lèi)是一個(gè)特殊的數(shù)組。通過(guò)添加和刪除元素,就可以動(dòng)態(tài)改變數(shù)組的長(zhǎng)度。
一.優(yōu)點(diǎn)
1. 支持自動(dòng)改變大小的功能
2. 可以靈活的插入元素
3. 可以靈活的刪除元素
二.局限性
跟一般的數(shù)組比起來(lái),速度上差些
三.添加元素
1.publicvirtualintAdd(objectvalue);
將對(duì)象添加到ArrayList的結(jié)尾處
ArrayList aList = new ArrayList(); aList.Add("a"); aList.Add("b"); aList.Add("c"); aList.Add("d"); aList.Add("e");
內(nèi)容為
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");
結(jié)果為
aaabcde
3.publicvirtualvoidInsertRange(intindex,ICollectionc);
將集合中的某個(gè)元素插入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);
結(jié)果為
abtttttcde
四.刪除
1. publicvirtualvoidRemove(objectobj);
從ArrayList中移除特定對(duì)象的第一個(gè)匹配項(xiàng),注意是第一個(gè)
ArrayList aList = new ArrayList(); aList.Add("a"); aList.Add("b"); aList.Add("c"); aList.Add("d"); aList.Add("e"); aList.Remove("a");
結(jié)果為
bcde
2. publicvirtualvoidRemoveAt(intindex);
移除ArrayList的指定索引處的元素
aList.Add("a"); aList.Add("b"); aList.Add("c"); aList.Add("d"); aList.Add("e"); aList.RemoveAt(0);
結(jié)果為
bcde
3.publicvirtualvoidRemoveRange(intindex,intcount);
從ArrayList中移除一定范圍的元素。Index表示索引,count表示從索引處開(kāi)始的數(shù)目
aList.Add("a"); aList.Add("b"); aList.Add("c"); aList.Add("d"); aList.Add("e"); aList.RemoveRange(1,3);
結(jié)果為
4.publicvirtualvoidClear();
從ArrayList中移除所有元素。
五.排序
1. publicvirtualvoidSort();
對(duì)ArrayList或它的一部分中的元素進(jìn)行排序。
ArrayListaList=newArrayList(); aList.Add("e"); aList.Add("a"); aList.Add("b"); aList.Add("c"); aList.Add("d"); DropDownList1.DataSource=aList;//DropDownListDropDownList1; DropDownList1.DataBind();
結(jié)果為
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();
結(jié)果為
abcde
2.publicvirtualvoidReverse();
將ArrayList或它的一部分中元素的順序反轉(zhuǎn)。
ArrayListaList=newArrayList(); aList.Add("a"); aList.Add("b"); aList.Add("c"); aList.Add("d"); aList.Add("e"); aList.Reverse();//反轉(zhuǎn) DropDownList1.DataSource=aList;//DropDownListDropDownList1; DropDownList1.DataBind();
結(jié)果為
edcba
六.查找
1.publicvirtualintIndexOf(object);
2. publicvirtualintIndexOf(object,int);
3. publicvirtualintIndexOf(object,int,int);
返回ArrayList或它的一部分中某個(gè)值的第一個(gè)匹配項(xiàng)的從零開(kāi)始的索引。沒(méi)找到返回-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”);//沒(méi)找到,-1
4.publicvirtualintLastIndexOf(object);
5.publicvirtualintLastIndexOf(object,int);
6.publicvirtualintLastIndexOf(object,int,int);
返回ArrayList或它的一部分中某個(gè)值的最后一個(gè)匹配項(xiàng)的從零開(kāi)始的索引。
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);
確定某個(gè)元素是否在ArrayList中。包含返回true,否則返回false
七.其他
1.publicvirtualintCapacity{get;set;}
獲取或設(shè)置ArrayList可包含的元素?cái)?shù)。
2.publicvirtualintCount{get;}
獲取ArrayList中實(shí)際包含的元素?cái)?shù)。
Capacity是ArrayList可以存儲(chǔ)的元素?cái)?shù)。Count是ArrayList中實(shí)際包含的元素?cái)?shù)。Capacity總是大于或等于Count。如果在添加元素時(shí),Count超過(guò)Capacity,則該列表的容量會(huì)通過(guò)自動(dòng)重新分配內(nèi)部數(shù)組加倍。
如果Capacity的值顯式設(shè)置,則內(nèi)部數(shù)組也需要重新分配以容納指定的容量。如果Capacity被顯式設(shè)置為0,則公共語(yǔ)言運(yùn)行庫(kù)將其設(shè)置為默認(rèn)容量。默認(rèn)容量為16。
在調(diào)用Clear后,Count為0,而此時(shí)Capacity切是默認(rèn)容量16,而不是0
3.publicvirtualvoidTrimToSize();
將容量設(shè)置為ArrayList中元素的實(shí)際數(shù)量。
如果不向列表中添加新元素,則此方法可用于最小化列表的內(nèi)存系統(tǒng)開(kāi)銷(xiāo)。
若要完全清除列表中的所有元素,請(qǐng)?jiān)谡{(diào)用TrimToSize之前調(diào)用Clear方法。截去空ArrayList會(huì)將ArrayList的容量設(shè)置為默認(rèn)容量,而不是零。
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 接口的一個(gè)實(shí)現(xiàn)類(lèi),內(nèi)部是用一個(gè)數(shù)組存儲(chǔ)元素值,相當(dāng)于一個(gè)可變大小的數(shù)組。
1.簽名
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable
可以看到ArrayList繼承了AbstractList抽象類(lèi),它實(shí)現(xiàn)了List接口的大多數(shù)方法。如果要實(shí)現(xiàn)一個(gè)不可變的List,只要繼承這個(gè)類(lèi)并且實(shí)現(xiàn)get(int)和size方法。如果要實(shí)現(xiàn)可變的List,需要覆蓋set(int, E)。另外,如果List的大小是可變的,還要覆蓋add(int, E)和remove()方法。
2.構(gòu)造器
ArrayList提供了三個(gè)構(gòu)造器:
ArrayList() ArrayList(Collection<? extends E> c) ArrayList(int initialCapacity)
Collection接口約定,每個(gè)集合類(lèi)應(yīng)該提供兩個(gè)”標(biāo)準(zhǔn)”構(gòu)造器,一個(gè)是無(wú)參數(shù)的構(gòu)造器(上面第一個(gè)),另外一個(gè)是擁有單個(gè)參數(shù)(類(lèi)型為Collettion)的構(gòu)造器(上面第二個(gè))。ArrayList還提供了第三個(gè)構(gòu)造器,其接受一個(gè)int值,用于設(shè)置ArrayLi的初始大小(默認(rèn)大小為10)。
3.相關(guān)方法
trimToSize public void trimToSize() { modCount++; int oldCapacity = elementData.length; if (size < oldCapacity) { elementData = Arrays.copyOf(elementData, size); } }
用于把ArrayList的容量縮減到當(dāng)前實(shí)際大小,減少存儲(chǔ)容量。其中的變量modCount由AbstracList繼承而來(lái),記錄List發(fā)生結(jié)構(gòu)化修改(structurally modified)的次數(shù)。elementData中實(shí)際存儲(chǔ)了ArrayList的元素,在ArrayList中聲明為:private transient Object[] elementData;變量size是ArrayList的元素?cái)?shù)量,當(dāng)size < oldCapacity時(shí),調(diào)用Arrays.copyOf方法實(shí)現(xiàn)縮減。
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; }
這兩個(gè)方法返回指定元素的下標(biāo),要區(qū)分參數(shù)是否為null。lastIndexOf和indexOf類(lèi)似,只不過(guò)是從后往前搜索。
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); }
這個(gè)方法可以確保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)向指定位置添加元素,首先調(diào)用rangeCheckForAdd檢查index是否有效,如果index > size || index < 0將拋出異常。然后確保容量加1,調(diào)用System.arraycopy把從index開(kāi)始的元素往后移動(dòng)一個(gè)位置。最后把index處的值設(shè)置為添加的元素。還有一個(gè)重載的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)方法刪除指定的元素。首先是查找元素位置,然后調(diào)用fastRemove(index)刪除,其代碼如下:
private void fastRemove(int index) { modCount++; int numMoved = size - index - 1; if (numMoved > 0) //把index+1往后的元素都往前移動(dòng)一個(gè)位置 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); }
它們都是通過(guò)調(diào)用batchRemove方法實(shí)現(xiàn)的,其代碼如下:
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; }
這個(gè)方法有兩個(gè)參數(shù),第一個(gè)是操作的Collection,第二個(gè)是一個(gè)布爾值,通過(guò)設(shè)置為true或false來(lái)選擇是removeAll還是retainAll。try里面的語(yǔ)句是把留下來(lái)的放在0到w之間,然后在finally中第二個(gè)if處理w之后的空間,第一個(gè)是在c.contains()拋出異常時(shí)執(zhí)行。
相關(guān)文章
JAVA動(dòng)態(tài)代理模式(從現(xiàn)實(shí)生活角度理解代碼原理)
本文主要介紹了JAVA動(dòng)態(tài)代理模式(從現(xiàn)實(shí)生活角度理解代碼原理)的相關(guān)知識(shí)。具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧2017-03-03MyBatis-Puls插入或修改時(shí)某些字段自動(dòng)填充操作示例
這篇文章主要為大家介紹了MyBatis-Puls插入或修改時(shí)某些字段自動(dòng)填充操作示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12記一次springboot服務(wù)凌晨無(wú)故宕機(jī)問(wèn)題的解決
這篇文章主要介紹了記一次springboot服務(wù)凌晨無(wú)故宕機(jī)問(wèn)題的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09java實(shí)現(xiàn)多線程交替打印兩個(gè)數(shù)
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)多線程交替打印兩個(gè)數(shù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11SpringBoot結(jié)合Ajax實(shí)現(xiàn)登錄頁(yè)面實(shí)例
大家好,本篇文章主要講的是SpringBoot結(jié)合Ajax實(shí)現(xiàn)登錄頁(yè)面實(shí)例,感興趣的同學(xué)趕快來(lái)看一看,對(duì)你有幫助的話(huà)記得收藏一下2022-02-02Java中的String對(duì)象數(shù)據(jù)類(lèi)型全面解析
首先String不屬于8種基本數(shù)據(jù)類(lèi)型,String是一個(gè)對(duì)象,因?yàn)閷?duì)象的默認(rèn)值是null,所以String的默認(rèn)值也是null;但它又是一種特殊的對(duì)象,有其它對(duì)象沒(méi)有的一些特性2012-11-11一文搞懂接口參數(shù)簽名與驗(yàn)簽(附含java python php版)
這篇文章主要為大家介紹了java python php不同版的接口參數(shù)簽名與驗(yàn)簽示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06