Arrays.asList

一般情況下,使用Arrays.asList()的原因無非是想將數組或一些元素轉爲集合,而你得到的集合並不一定是你想要的那個集合

asList在最初設計時用於打印數組,但jdk1.5開始,有了另一個比較更方便的打印函數Arrays.toString(),於是打印不再使用asList(),而asList()恰巧可用於將數組轉爲集合。

一、首先看幾個例子:

(1)將基本類型數組作爲asList參數

		String[] strArr = {"A","B","C"};
		List<String> asList = Arrays.asList(strArr);
		System.out.println("封裝類型String時:" + asList.size());

		int[] intArr = {1, 2, 3};
		List<String> list = Arrays.asList(intArr);
		System.out.println("基本類型時:" + list.size());

運行結果:

封裝類型String時:3
基本類型時:1

(2)將數組作爲asList參數後,修改數組或List

		String[] strArr = {"A","B","C"};
		List<String> asList = Arrays.asList(strArr);
		strArr[0] = "a";
		asList.set(1, "b");
		System.out.println(Arrays.toString(strArr));
		System.out.println(asList.toString());

運行結果:

[a, b, C]
[a, b, C]

strArr和asList 中的數據都會改變

(3)數組轉換爲集合後,進行增刪元素

		String[] strArr = {"A","B","C"};
		List<String> asList = Arrays.asList(strArr);
		asList.add("1");
		asList.remove("C");
		System.out.println(asList.toString());

運行結果:

Exception in thread "main" java.lang.UnsupportedOperationException
	at java.util.AbstractList.add(AbstractList.java:148)
	at java.util.AbstractList.add(AbstractList.java:108)
	at com.my.tests.TestArrayAsList.main(TestArrayAsList.java:9)

二、深入研究

這裏要關注的地方在於:
Arrays.asList()返回的List是:Arrays.ArrayList,而不是java.util.ArrayList
在這裏插入圖片描述
兩者的不同之處:
Arrays.ArrayList是工具類Arrays的一個內部靜態類,它沒有完全實現List方法,而ArrayList直接實現了List接口,實現了List所有方法。

  • 長度不同和實現的方法不同:
    Arrays.ArrayList是一個定長集合,因爲它沒有重寫add,remove方法,所以,一旦初始化元素後,集合的size就是不可變的。
  • 參數賦值方式不同
    Arrays.ArrayList將外部數組的引用直接通過“=”賦予內部的泛型數組,所以本質指向同一個數組。而ArrayList是將其他集合轉爲數組後copy到自己內部的數組的。
// 以下是JDK8版本中的Arrays.ArrayList
    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 final E[] a;

        ArrayList(E[] array) {
            a = Objects.requireNonNull(array);	// 此處是直接賦值的,所以本質指向的是同一個數組
     	}
   	}

// 以下是JDK8中java.util.ArrayList
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();	// toArray底層使用的是數組clone或System.arraycopy
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

在這裏插入圖片描述

三、案例解析

對於第一個例子:(1)將基本類型數組作爲asList參數
由於Arrays.ArrayList參數爲可變長泛型,而基本類型是無法泛型化的,所以它把int[] arr數組當成了一個泛型對象,所以集合中最終只有一個元素arr。

對於第二個例子:(2)將數組作爲asList參數後,修改數組或List
由於asList產生的集合元素是直接引用作爲參數的數組,所以當外部數組或集合改變時,數組和集合會同步變化,這在平時我們編碼時可能產生莫名的問題。

對於第三個例子:(3)數組轉換爲集合後,進行增刪元素
由於asList產生的集合並沒有重寫add,remove等方法,所以它會調用父類AbstractList的方法,而父類的方法中拋出的卻是異常信息。

四、支持基礎類型的方式

1、如果使用Spring

import org.springframework.util.CollectionUtils;

public class Temp {
	public static void main(String[] args) {
		int[] arr = {1,2,3};
		List list = CollectionUtils.arrayToList(arr);
		System.out.println(list);
	}
}

運行結果:

[1, 2, 3]

2、直接使用Java8

		int intArray[] = {1,2,3};
		List<Integer> iList = Arrays.stream(intArray)
				.boxed()
				.collect(Collectors.toList());
		System.out.println(iList);

運行結果:

[1, 2, 3]

五、數組轉ArrayList

1、遍歷轉換

		Integer intArray[] = {1,2,3};
		ArrayList<Integer> arrayList = new ArrayList<>();
		for (Integer i : arrayList) {
			arrayList.add(i);
		}

2、使用工具類(更加優雅)

		ArrayList<String> list = new ArrayList();
		Collections.addAll(list, "A", "B", "C");

3、對於JAVA8
既可以用於基本類型也可以返回想要的集合。

		int intArray[] = {1,2,3};
		List<Integer> iList = Arrays.stream(intArray)
				.boxed()
				.collect(Collectors.toList());
		System.out.println(iList);

運行結果:

[1, 2, 3]

4、還有另外一種方法
兩個集合類結合:將Arrays.asList返回的集合作爲ArrayList的構造參數

		ArrayList arrayList = new ArrayList<>(
				Arrays.asList("A", "B", "C")
				);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章