源碼解析:java.util.ArrayList和java.util.Arrays.ArrayList之間的區(qū)別,以及用法注意


有時候我們需要將數(shù)組轉成List集合對象,這時我們可以使用java.util.Arrays的asList方法,例如:

String[] strArray = new String[] {"aaa", "bbb"};
List<String> strList = Arrays.asList(strArray);

將對轉換后的strList對象添加一個新的元素:strList.add(“ccc”);
執(zhí)行這段代碼,但是拋出如下異常信息:

Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.AbstractList.add(AbstractList.java:148)
    at java.util.AbstractList.add(AbstractList.java:108)

為什么會拋出異常,并且顯示不支持add方法了?

我們看看傳統(tǒng)的標準集合類ArrayList以及add用法:

ArrayList是java中標準的集合類,可以通過他創(chuàng)建一個list集合,并且他提供了add等方法可以添加、修改集合元素,例如:

List<String> strList = new ArrayList<String>();
strList.add("aaa");
strList.add("bbb");
strList.add("ccc");
System.out.println(strList);

輸出的結果:[aaa, bbb, ccc]

同樣是List對象,前者可以正常執(zhí)行,而后者卻執(zhí)行失敗,原因在于兩者的實現(xiàn)不同,從jdk的源碼可以得到相應的答案:

Arrays.asList方法的實現(xiàn):

public static <T> List<T> asList(T... a) {
    return new ArrayList<>(a);
}

是直接通過new出一個ArrayList對象完成,但是注意,這里的ArrayList并不是java.util.ArrayList對象,而是Arrays類里面自己實現(xiàn)的一個同名的ArrayList,大致的結構如下:

private static class ArrayList<E> extends AbstractList<E>
    implements RandomAccess, java.io.Serializable
{
    private static final long serialVersionUID = -2764017481108945198L;
    private final E[] a;
    ArrayList(E[] array) {
        if (array==null)
            throw new NullPointerException();
        a = array;
    }
    …...
}

在內部創(chuàng)建了一個不可變的數(shù)組a(private final E[] a),但這并不能解決我們?yōu)槭裁床荒苓M行add操作,點開這個類的add方法實現(xiàn):

public boolean add(E e) {
    add(size(), e);
    return true;
}

程序內部調用了:

public void add(int index, E element) {
    throw new UnsupportedOperationException();
}

從這里可以看出,為什么會當我們使用add操作的時候回拋出UnsupportedOperationException異常了,因為這個ArrayList并沒有實現(xiàn)add方法。

來看一下java.util.ArrayList的add方法實現(xiàn):

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

可以看到其實它的內部也是通過一個數(shù)組對象完成的操作,但是在對數(shù)組進行操作之前,調用了ensureCapacityInternal方法,而該方法最終調用了一個grow方法,該方法的源碼如下:

private void grow(int minCapacity) {
    …...
    elementData = Arrays.copyOf(elementData, newCapacity);
}

而這個方法的主要目的就是,判斷是否需要新增一個新的數(shù)組將原先不能容下的所有數(shù)據(jù)移動到新數(shù)組里面。

在每次add的時候都會做一次這樣的判斷,這樣的數(shù)組移動如果比較頻繁,是非常消耗資源的,所有在使用ArrayList數(shù)組的時候需要注意以下的幾個問題:

  • 在創(chuàng)建ArrayList數(shù)組的時候,根據(jù)你需要的數(shù)量判斷,所以在創(chuàng)建ArrayList的時候指定初始的List長度,例new ArrayList<String>(20);如果不指定,默認的list長度為10.
  • ArrayList的add方法常常會引起性能問題,所以,如果需要頻繁的插入、刪除最好是換成LinkedList這種以鏈表方式實現(xiàn)的集合。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,734評論 18 399
  • Java 語言支持的類型分為兩類:基本類型和引用類型。整型(byte 1, short 2, int 4, lon...
    xiaogmail閱讀 1,450評論 0 10
  • 文章有點長,比較啰嗦,請耐心看完?。ɑ贏ndroid API 25) 一、概述 首先得明白ArrayList在數(shù)...
    JerryloveEmily閱讀 3,382評論 2 15
  • java筆記第一天 == 和 equals ==比較的比較的是兩個變量的值是否相等,對于引用型變量表示的是兩個變量...
    jmychou閱讀 1,656評論 0 3
  • 這場比賽贏得很輕松,因為思路正確! 我走的中路,帶了眩暈! 對線一段時間之后,我開始打野區(qū)的資源!升級快,錢多。 ...
    烏龜?shù)穆?/span>閱讀 311評論 0 0

友情鏈接更多精彩內容