基礎篇--ArrayList擴容__Java基礎常識

來源:互聯網
上載者:User

首先,我們來看ArrayList的繼承關係如下,從表面上我們可以看到它支援抽象對象的方法


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

我們來看看都繼承了哪些方法

   AbstractList 一個抽象類別,裡面會有一些常用方法的實現

   List介面必須實現方法

  randomAccess是一個空介面,起到一個標識的作用,在AbstractList會有用到,這裡暫不討論

  Colneable 與randomAccess類似也是一個空介面,提供了Object.colne()方法

  Serializable 介面以啟用其序列化功能


ArrayList用到了兩個全域變數,對於多線程稍微瞭解一點,也應該能夠知道,從這裡就可以看出ArrayList也出現並發問題,非安全執行緒類

 

Object[] elementData 數群組類型

/**     * The array buffer into which the elements of the ArrayList are stored.     * The capacity of the ArrayList is the length of this array buffer.     */    private transient Object[] elementData;    /**     * The size of the ArrayList (the number of elements it contains).     *     * @serial     */    private int size;

List list = new ArrayList();//這是我們常用的建立方式,我們來看看內部會發生什麼。

  預設對象屬性為10,為數組形式

    /**     * Constructs an empty list with the specified initial capacity.     *     * @param  initialCapacity  the initial capacity of the list     * @throws IllegalArgumentException if the specified initial capacity     *         is negative     */    public ArrayList(int initialCapacity) {        super();        if (initialCapacity < 0)            throw new IllegalArgumentException("Illegal Capacity: "+                                               initialCapacity);        this.elementData = new Object[initialCapacity];// <span style="color:#FF0000;">數群組類型</span>    }    /**     * Constructs an empty list with an initial capacity of ten.     */    public ArrayList() {        this(10); // <span style="color:#FF0000;">預設10個元素</span>    }

接下來進入主題,來看看它的添加方法

<span style="font-size:14px;">/**     * Appends the specified element to the end of this list.     *     * @param e element to be appended to this list     * @return <tt>true</tt> (as specified by {@link Collection#add})     */    public boolean add(E e) {        ensureCapacityInternal(size + 1);  // Increments modCount!!        elementData[size++] = e;        return true;    }</span>

重點來了,我們知道初始元素個數為10,那麼如果滿了會發生什麼呢

<span style="font-size:14px;">private void ensureCapacityInternal(int minCapacity) {        modCount++;        // overflow-conscious code        if (minCapacity - elementData.length > 0)            grow(minCapacity);    }</span>

<span style="font-size:14px;">  </span><pre name="code" class="java"><span style="font-size:14px;">   private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;</span>


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

 

從這裡我們可以看到,每次的擴容增量為  (1 + 0.5) * oldCapacity,最大為

<pre name="code" class="java"><span style="font-size:14px;">Integer.MAX_VALUE</span>

 

並且每次的擴容會重新建立一個對象

<span style="font-size:14px;">    public static <T,U> T[] 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;    }</span>

設想一下,如果每次添加一個元素,一直添加10萬百萬個元素,會建立多少個對象


最簡單的最佳化方法,在建立list的時候,我們是否可以預估一下預計的個數呢。每次添加元素之前  我們是否可以預估一下要擴容元素的個數呢。


<span style="font-size:14px;">ArrayList list = new ArrayList(100);// 更改預設值100        list.ensureCapacity(1000); // 預估擴容1000</span>


如果有其他的好的擴容方法,歡迎討論


測試如下

public static void main(String[] args) throws IOException {        Runtime run = Runtime.getRuntime();        run.gc();        System.out.println("time: " + (new Date()));        // 擷取開始時記憶體使用量量        long startMem = run.totalMemory() - run.freeMemory();        System.out.println("memory> total:" + run.totalMemory() + " free:" + run.freeMemory() + " used:" + startMem);        ArrayList list = new ArrayList();        int size = 10000000;//        list.ensureCapacity(size);  // 是否擴容        int i = 0;        try {            for (; i < size; i++) {                list.add(i);            }        } catch (Throwable e) {            e.printStackTrace();            System.out.println("i= " + i);        }        System.out.println("time: " + (new Date()));        long endMem = run.totalMemory() - run.freeMemory();        System.out.println("memory> total:" + run.totalMemory() + " free:" + run.freeMemory() + " used:" + endMem);        System.out.println("memory difference:" + (endMem - startMem));    }


輸出記憶體差異結果結果:

a.不擴容

time: Tue Aug 23 16:38:49 CST 2016
memory> total:18350080 free:16858832 used:1491248
time: Tue Aug 23 16:38:53 CST 2016
memory> total:291962880 free:14030184 used:277932696
memory difference:276441448


b.擴容


time: Tue Aug 23 16:41:47 CST 2016
memory> total:18612224 free:17107928 used:1504296
time: Tue Aug 23 16:41:50 CST 2016
memory> total:296026112 free:94840808 used:201185304
memory difference:199681008


















聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.