摘要:注意,迭代器的快速失敗行為無(wú)法得到保證,快速失敗迭代器會(huì)盡最大努力拋出。迭代器的快速失敗行為應(yīng)該僅用于檢測(cè)。
幾個(gè)重要接口
首先看方法聲明:
public class ArrayListextends AbstractList implements List , RandomAccess, Cloneable, java.io.Serializable
RandomAccess:
public interface RandomAccess { }
RandomAccess接口都是給 List所使用的,用來(lái)表明其支持快速(通常是固定時(shí)間)隨機(jī)訪問(wèn),為其提供良好的性能。實(shí)際經(jīng)驗(yàn)證明,如果是下列情況,則 List 實(shí)現(xiàn)應(yīng)該實(shí)現(xiàn)此接口,即對(duì)于典型的類(lèi)實(shí)例而言,此循環(huán):
for (int i=0, n=list.size(); i < n; i++) list.get(i);
的運(yùn)行速度要快于以下循環(huán):
for (Iterator i=list.iterator(); i.hasNext(); ) i.next();
Cloneable:
public interface Cloneable { }
實(shí)現(xiàn)了此接口的類(lèi)就可以通過(guò)重寫(xiě) Object.clone()方法來(lái)定制對(duì)其進(jìn)行復(fù)制的細(xì)節(jié),如果在沒(méi)有實(shí)現(xiàn) Cloneable 接口的實(shí)例上調(diào)用 Object 的 clone 方法,則會(huì)導(dǎo)致拋出 CloneNotSupportedException 異常。
兩個(gè)變量/** * ArrayList中元素存儲(chǔ)的地方,數(shù)組的長(zhǎng)度就是它的容量 */ private transient Object[] elementData; /** *ArrayList所包含的元素的大小 */ private int size;構(gòu)造方法
提供了3種構(gòu)造方法:
public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; } public ArrayList() { this(10); } public ArrayList(Collection extends E> c) { elementData = c.toArray(); size = elementData.length; // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); }
可以看到:第一種方法需要一個(gè)默認(rèn)的容量大小,第二個(gè)是默認(rèn)的構(gòu)造方法,會(huì)默認(rèn)創(chuàng)建一個(gè)容量為10的 ArrayList,第三個(gè)則傳給一個(gè) Collection,注意,不管 Collection里面是什么類(lèi)型,最后放進(jìn) ArrayList都會(huì)上轉(zhuǎn)為 Object
重要方法 addpublic boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }
add方法中使用了 ensureCapacityInternal來(lái)控制容量:
private void ensureCapacityInternal(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); }
其中 modCount是用來(lái)記錄 list被結(jié)構(gòu)修改的次數(shù),所謂結(jié)構(gòu)上的修改是 指任何添加或刪除一個(gè)或多個(gè)元素的操作,或者顯式調(diào)整底層數(shù)組的大小;僅僅設(shè)置元素的值不是結(jié)構(gòu)上的修改;在上面的方法中,如果 minCapacity 大于現(xiàn)有數(shù)組長(zhǎng)度,則執(zhí)行 grow方法:
private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; /*newCapacity 擴(kuò)展為舊容量的1.5倍左右*/ int newCapacity = oldCapacity + (oldCapacity >> 1); /*如果這時(shí)新容量還小于minCapacity,則新容量為minCapacity*/ if (newCapacity - minCapacity < 0) newCapacity = minCapacity; /*新容量大于 Integer.MAX_VALUE - 8*/ if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // 最后將原數(shù)組放進(jìn)新數(shù)組,改變長(zhǎng)度 elementData = Arrays.copyOf(elementData, newCapacity); }
如果 newCapacity大于 Integer.MAX_VALUE - 8,則 newCapacity為 Integer.MAX_VALUE,這也是能夠擴(kuò)充的最大容量
再來(lái)看第二種 add方法:
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++; }
這種方法是在指定位置插入元素,主要使用了 System.arraycopy()方法將 index之后的元素向后移動(dòng)一個(gè)位置,將 index位空出來(lái)放入新元素
clearclear方法比較簡(jiǎn)單,但是注意調(diào)用 clear也會(huì)使 modCount加1:
public void clear() { modCount++; // Let gc do its work for (int i = 0; i < size; i++) elementData[i] = null; size = 0; }clone
public Object clone() { try { @SuppressWarnings("unchecked") ArrayListv = (ArrayList ) super.clone(); v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0; return v; } catch (CloneNotSupportedException e) { // this shouldn"t happen, since we are Cloneable throw new InternalError(); } }
clone方法只能進(jìn)行淺復(fù)制,并不復(fù)制元素本身
removepublic 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方法中,如果要移除的元素為 null,則刪除數(shù)組中第一個(gè)為 null的元素。如果數(shù)組中有超過(guò)一個(gè)匹配的元素,僅移除第一個(gè)
toArraypublic Object[] toArray() { return Arrays.copyOf(elementData, size); }
這個(gè)方法被很多方法使用,它調(diào)用了 Arrays工具類(lèi)中的方法 copyOf:
public staticT[] copyOf(T[] original, int newLength) { return (T[]) copyOf(original, newLength, original.getClass()); }
public staticT[] copyOf(U[] original, int newLength, Class extends T[]> newType) { 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)); return copy; }
最終調(diào)用了方法:
public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length)
它的參數(shù)列表如下:
src - 源數(shù)組。
srcPos - 源數(shù)組中的起始位置。
dest - 目標(biāo)數(shù)組。
destPos - 目標(biāo)數(shù)據(jù)中的起始位置。
length - 要復(fù)制的數(shù)組元素的數(shù)量。
從指定源數(shù)組中復(fù)制一個(gè)數(shù)組,復(fù)制從指定的位置開(kāi)始,到目標(biāo)數(shù)組的指定位置結(jié)束。這個(gè)方法是一個(gè) native方法,并且經(jīng)測(cè)試,如果是引用數(shù)組類(lèi)型,它不會(huì)真正復(fù)制對(duì)象,只是復(fù)制引用(淺復(fù)制)
trimToSize將此 ArrayList 實(shí)例的容量調(diào)整為列表的當(dāng)前大小。應(yīng)用程序可以使用此操作來(lái)最小化 ArrayList 實(shí)例的存儲(chǔ)量。
public void trimToSize() { modCount++; int oldCapacity = elementData.length; if (size < oldCapacity) { elementData = Arrays.copyOf(elementData, size); } }
由此可知:在 ArrayList容量確定下來(lái)以后,可以調(diào)用這個(gè)方法最小化存儲(chǔ)空間
Fast-Fail快速失敗機(jī)制此類(lèi)的 iterator 和 listIterator 方法返回的迭代器是快速失敗的:在創(chuàng)建迭代器之后,除了通過(guò)迭代器自身的 remove 或 add 方法從結(jié)構(gòu)上對(duì)列表進(jìn)行修改,否則在任何時(shí)間以任何方式對(duì)列表進(jìn)行修改,迭代器都會(huì)拋出 ConcurrentModificationException。因此,面對(duì)并發(fā)的修改,迭代器很快就會(huì)完全失敗,而不是冒著在將來(lái)某個(gè)不確定時(shí)間發(fā)生任意不確定行為的風(fēng)險(xiǎn)。
注意,迭代器的快速失敗行為無(wú)法得到保證,快速失敗迭代器會(huì)盡最大努力拋出 ConcurrentModificationException。迭代器的快速失敗行為應(yīng)該僅用于檢測(cè) bug。
前面說(shuō)到 ArrayList中定義了一個(gè) modCount來(lái)記錄對(duì)容器進(jìn)行結(jié)構(gòu)修改的次數(shù),在 add、 addAll、 remove、 clear、 clone方法中都會(huì)引起 modCount變化,而在創(chuàng)建迭代器時(shí),會(huì)使用局部變量保存當(dāng)前的 modCount值:
private class Itr implements Iterator{ int cursor; // index of next element to return int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount; ...
在進(jìn)行迭代的過(guò)程中,會(huì)先檢查 modCount 有沒(méi)有發(fā)生變化,以此來(lái)判定是否有外部操作改變了容器:
final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); }
最后,因?yàn)?ArrayList是非同步的,因此,在多線程環(huán)境下,如果有對(duì)容器進(jìn)行結(jié)構(gòu)修改的操作,則必須使用外部同步。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/64428.html
摘要:同步眾所周知,是同步的而不是,在一些必要的方法上都加了關(guān)鍵字,但是這也會(huì)加大系統(tǒng)開(kāi)銷(xiāo)。中有一個(gè)方法用來(lái)返回一個(gè),以匿名內(nèi)部類(lèi)的方式實(shí)現(xiàn)的接口和類(lèi)似,都用作于對(duì)集合進(jìn)行迭代,不過(guò)沒(méi)有刪除功能,已經(jīng)被取代。還有是的,但不是,這一點(diǎn)很重要。 在上篇文章ArrayList源碼淺析中分析了一下 ArrayList的源碼和一些重要方法,現(xiàn)在對(duì)比 ArrayList,總結(jié)一下 Vector和 Arr...
摘要:重要方法在鏈尾添加元素除了這個(gè)方法以外,還提供了等一些方法,都是為實(shí)現(xiàn)和方法服務(wù)的,因?yàn)殡p向鏈表的原因,這些實(shí)現(xiàn)都很簡(jiǎn)單。 類(lèi)聲明 LinkedList類(lèi)聲明如下: public class LinkedList extends AbstractSequentialList implements List, Deque, Cloneable, java.io.Seria...
摘要:它主要做了件事初始化容器,并將元素添加到容器里維護(hù)這樣我們?cè)僬{(diào)用的方法直接就返回了,不需要再次遍歷和統(tǒng)計(jì)的過(guò)程。維護(hù)實(shí)時(shí)的維護(hù),及時(shí)刪除總結(jié)整體上是對(duì)底層的二次封裝,很好的處理了各種細(xì)節(jié),比如子容器的判空處理,的計(jì)算效率,的維護(hù)等。 在日常開(kāi)發(fā)中我們通常有需要對(duì) List 容器進(jìn)行分組的情況,比如對(duì)下面的list數(shù)據(jù)根據(jù)name字段來(lái)進(jìn)行分組: [ { date...
摘要:是非,而是,這意味著是線程安全的,多個(gè)線程可以共享一個(gè)而如果沒(méi)有正確的同步的話,多個(gè)線程是不能共享的。另一個(gè)區(qū)別是的迭代器是迭代器,而的迭代器不 這里只解析一些常用的、比較重要的一些集合類(lèi),并且作者水平有限,有些地方可能解析不到位或者解析錯(cuò)誤,還望各位讀者指出錯(cuò)誤。 Collection List ArrayList LinkedLis...
摘要:泛型類(lèi)在類(lèi)的申明時(shí)指定參數(shù),即構(gòu)成了泛型類(lèi)。換句話說(shuō),泛型類(lèi)可以看成普通類(lèi)的工廠。的作用就是指明泛型的具體類(lèi)型,而類(lèi)型的變量,可以用來(lái)創(chuàng)建泛型類(lèi)的對(duì)象。只有聲明了的方法才是泛型方法,泛型類(lèi)中的使用了泛型的成員方法并不是泛型方法。 什么是泛型? 泛型是JDK 1.5的一項(xiàng)新特性,它的本質(zhì)是參數(shù)化類(lèi)型(Parameterized Type)的應(yīng)用,也就是說(shuō)所操作的數(shù)據(jù)類(lèi)型被指定為一個(gè)參數(shù),...
閱讀 2530·2023-04-26 02:47
閱讀 3012·2023-04-26 00:42
閱讀 878·2021-10-12 10:12
閱讀 1385·2021-09-29 09:35
閱讀 1699·2021-09-26 09:55
閱讀 487·2019-08-30 14:00
閱讀 1542·2019-08-29 12:57
閱讀 2362·2019-08-28 18:00