国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

ArrayList源碼淺析

h9911 / 3478人閱讀

摘要:注意,迭代器的快速失敗行為無法得到保證,快速失敗迭代器會盡最大努力拋出。迭代器的快速失敗行為應該僅用于檢測。

幾個重要接口

首先看方法聲明:

public class ArrayList extends AbstractList
        implements List, RandomAccess, Cloneable, java.io.Serializable

RandomAccess:

public interface RandomAccess {
}

RandomAccess接口都是給 List所使用的,用來表明其支持快速(通常是固定時間)隨機訪問,為其提供良好的性能。實際經驗證明,如果是下列情況,則 List 實現應該實現此接口,即對于典型的類實例而言,此循環:

for (int i=0, n=list.size(); i < n; i++)
         list.get(i);

的運行速度要快于以下循環:

for (Iterator i=list.iterator(); i.hasNext(); )
         i.next();

Cloneable:

public interface Cloneable {
}

實現了此接口的類就可以通過重寫 Object.clone()方法來定制對其進行復制的細節,如果在沒有實現 Cloneable 接口的實例上調用 Objectclone 方法,則會導致拋出 CloneNotSupportedException 異常。

兩個變量
/**
* ArrayList中元素存儲的地方,數組的長度就是它的容量
*/
private transient Object[] elementData;

/**
 *ArrayList所包含的元素的大小 
*/
private int size;
構造方法

提供了3種構造方法:

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 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);
    }    

可以看到:第一種方法需要一個默認的容量大小,第二個是默認的構造方法,會默認創建一個容量為10的 ArrayList,第三個則傳給一個 Collection,注意,不管 Collection里面是什么類型,最后放進 ArrayList都會上轉為 Object

重要方法 add
 public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

add方法中使用了 ensureCapacityInternal來控制容量:

private void ensureCapacityInternal(int minCapacity) {
        modCount++;
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

其中 modCount是用來記錄 list被結構修改的次數,所謂結構上的修改是 指任何添加或刪除一個或多個元素的操作,或者顯式調整底層數組的大小;僅僅設置元素的值不是結構上的修改;在上面的方法中,如果 minCapacity 大于現有數組長度,則執行 grow方法:

private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        /*newCapacity 擴展為舊容量的1.5倍左右*/
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        /*如果這時新容量還小于minCapacity,則新容量為minCapacity*/
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        /*新容量大于 Integer.MAX_VALUE - 8*/    
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // 最后將原數組放進新數組,改變長度
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

如果 newCapacity大于 Integer.MAX_VALUE - 8,則 newCapacityInteger.MAX_VALUE,這也是能夠擴充的最大容量

再來看第二種 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之后的元素向后移動一個位置,將 index位空出來放入新元素

clear

clear方法比較簡單,但是注意調用 clear也會使 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")
            ArrayList v = (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方法只能進行淺復制,并不復制元素本身

remove
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方法中,如果要移除的元素為 null,則刪除數組中第一個為 null的元素。如果數組中有超過一個匹配的元素,僅移除第一個

toArray
public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }

這個方法被很多方法使用,它調用了 Arrays工具類中的方法 copyOf

public static  T[] copyOf(T[] original, int newLength) {
        return (T[]) copyOf(original, newLength, original.getClass());
    }
public static  T[] copyOf(U[] original, int newLength, Class 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;
    }

最終調用了方法:

public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length)

它的參數列表如下:

src - 源數組。
srcPos - 源數組中的起始位置。
dest - 目標數組。
destPos - 目標數據中的起始位置。
length - 要復制的數組元素的數量。

從指定源數組中復制一個數組,復制從指定的位置開始,到目標數組的指定位置結束。這個方法是一個 native方法,并且經測試,如果是引用數組類型,它不會真正復制對象,只是復制引用(淺復制)

trimToSize

將此 ArrayList 實例的容量調整為列表的當前大小。應用程序可以使用此操作來最小化 ArrayList 實例的存儲量。

public void trimToSize() {
        modCount++;
        int oldCapacity = elementData.length;
        if (size < oldCapacity) {
            elementData = Arrays.copyOf(elementData, size);
        }
    }

由此可知:在 ArrayList容量確定下來以后,可以調用這個方法最小化存儲空間

Fast-Fail快速失敗機制

此類的 iteratorlistIterator 方法返回的迭代器是快速失敗的:在創建迭代器之后,除了通過迭代器自身的 removeadd 方法從結構上對列表進行修改,否則在任何時間以任何方式對列表進行修改,迭代器都會拋出 ConcurrentModificationException。因此,面對并發的修改,迭代器很快就會完全失敗,而不是冒著在將來某個不確定時間發生任意不確定行為的風險。
注意,迭代器的快速失敗行為無法得到保證,快速失敗迭代器會盡最大努力拋出 ConcurrentModificationException。迭代器的快速失敗行為應該僅用于檢測 bug。
前面說到 ArrayList中定義了一個 modCount來記錄對容器進行結構修改的次數,在 addaddAllremoveclearclone方法中都會引起 modCount變化,而在創建迭代器時,會使用局部變量保存當前的 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;
        ...

在進行迭代的過程中,會先檢查 modCount 有沒有發生變化,以此來判定是否有外部操作改變了容器:

 final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }

最后,因為 ArrayList是非同步的,因此,在多線程環境下,如果有對容器進行結構修改的操作,則必須使用外部同步。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/64428.html

相關文章

  • Vector源碼分析(對比ArrayList

    摘要:同步眾所周知,是同步的而不是,在一些必要的方法上都加了關鍵字,但是這也會加大系統開銷。中有一個方法用來返回一個,以匿名內部類的方式實現的接口和類似,都用作于對集合進行迭代,不過沒有刪除功能,已經被取代。還有是的,但不是,這一點很重要。 在上篇文章ArrayList源碼淺析中分析了一下 ArrayList的源碼和一些重要方法,現在對比 ArrayList,總結一下 Vector和 Arr...

    wall2flower 評論0 收藏0
  • LinkedList源碼淺析

    摘要:重要方法在鏈尾添加元素除了這個方法以外,還提供了等一些方法,都是為實現和方法服務的,因為雙向鏈表的原因,這些實現都很簡單。 類聲明 LinkedList類聲明如下: public class LinkedList extends AbstractSequentialList implements List, Deque, Cloneable, java.io.Seria...

    DC_er 評論0 收藏0
  • 淺析guava容器multimap

    摘要:它主要做了件事初始化容器,并將元素添加到容器里維護這樣我們再調用的方法直接就返回了,不需要再次遍歷和統計的過程。維護實時的維護,及時刪除總結整體上是對底層的二次封裝,很好的處理了各種細節,比如子容器的判空處理,的計算效率,的維護等。 在日常開發中我們通常有需要對 List 容器進行分組的情況,比如對下面的list數據根據name字段來進行分組: [ { date...

    yy13818512006 評論0 收藏0
  • Java 集合框架淺析

    摘要:是非,而是,這意味著是線程安全的,多個線程可以共享一個而如果沒有正確的同步的話,多個線程是不能共享的。另一個區別是的迭代器是迭代器,而的迭代器不 這里只解析一些常用的、比較重要的一些集合類,并且作者水平有限,有些地方可能解析不到位或者解析錯誤,還望各位讀者指出錯誤。 Collection List ArrayList LinkedLis...

    LeviDing 評論0 收藏0
  • 淺析Java泛型

    摘要:泛型類在類的申明時指定參數,即構成了泛型類。換句話說,泛型類可以看成普通類的工廠。的作用就是指明泛型的具體類型,而類型的變量,可以用來創建泛型類的對象。只有聲明了的方法才是泛型方法,泛型類中的使用了泛型的成員方法并不是泛型方法。 什么是泛型? 泛型是JDK 1.5的一項新特性,它的本質是參數化類型(Parameterized Type)的應用,也就是說所操作的數據類型被指定為一個參數,...

    godiscoder 評論0 收藏0

發表評論

0條評論

h9911

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<