使用List需要注意的點


1. 概述

在使用List集合時有些地方需要注意一下的, 不然會出現一些莫名其妙的錯誤.

2. Arrays.asList();

2-1. 產生不可操作的集合

來看一個例子.

Integer[] array = {1, 2, 3, 4, 5};
List<Integer> list = Arrays.asList(array);
list.remove(1);

會直接拋出java.lang.UnsupportedOperationException異常, 為什么呢?

答案是: 返回的List非java.util.ArrayList. 而是在Arrays類內部有一個靜態內部類叫ArrayList.

靜態內部類ArrayList並沒有提供所有的方法實現, 有些方法在抽象類中僅僅是一個拋異常的實現, 上述的remove就是這種情況. asList返回的列表只不過是披着list的外衣, 它並沒有list的基本特性(變長), 該list是一個長度不可變的列表, 傳入參數的數組有多長, 其返回的列表就只能是多長. 所以不要試圖改變asList的返回列表.

Arrays.asList的代碼如下:

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

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) {
        a = Objects.requireNonNull(array);
    }

    // 省略部分源碼
}

該類也是繼承了AbstractkList抽象類, 只是該類並沒有提供所有方法的實現.

2-2. 需要傳入對象數組而不是基本類型數組

看個例子:

int[] array1 = {1, 2, 3, 4, 5};
List<int[]> list1 = Arrays.asList(array1);
System.out.println(list1.size()); // 1

Integer[] array2 = {1, 2, 3, 4, 5};
List<Integer> list2 = Arrays.asList(array2);
System.out.println(list2.size()); // 5

看到Array.asList的返回值的泛型就明白, list1中存儲的實際是一個數組. 為什么這樣呢? 數值類型不能被泛型化, 比如List<int>是不對的, 必須是List<Integer>才對.

3. arrayList.subList();

3-1. subList返回的並不是ArrayList

方法返回的是一個內部類SubList, 並不是ArrayList, SubList也是繼承AbstractList, 內部引用了原列表的List.

3-2. subList返回的僅僅是一個視圖

subList返回的僅僅是一個視圖, 對subList返回值的所有操作都會作用在原列表中.

看一個例子

List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
list.add("E");

List<String> subList = list.subList(2, 4);
subList.add("F");
System.out.println(list); // 輸出 [A, B, C, D, F, E]

通過輸出結果可知, F被添加到原列表中了.

3-3. 生成子列表時, 不要試圖去操作原列表

因為子列表是根據原列表動態生成的, 所以如果原列表變了, 那么操作子列表時就會發生ConcurrentModificationException異常. 這個異常的原因相信你也知道, 就是modCount改變了導致的.

3-4. 推薦使用subList處理局部鏈表

比如, 有一個需求要刪除列表100-200位置處的數據, 通常我們這樣寫:

int start = 100;
int end = 200;
for (int i = start; i <= end; i++) {
    list.remove(start);
}

通過subList, 我們有一個更簡潔的處理方式:

list.subList(100, 200).clear();

簡潔.

不定期更新

可能還會遇到集合相關的坑.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM