1. 程式人生 > >Java集合與陣列的轉換

Java集合與陣列的轉換

陣列轉化為集合

使用Arrays.asList包裝器可以達到這個目的。

public static <T> List<T> asList(T... a) {
    return new ArrayList<>(a);
}
如上所示,函式引數是Varargs(可變引數), 採用了泛型實現。同時由於autoboxing的支援,使得可以支援物件陣列以及基本型別陣列。

不過在使用時,當傳入基本資料型別的陣列時,會出現小問題,會把傳入的陣列整個當作返回的List中的第一個元素,例如:

int[] arr1 = new int[]{111, 222, 333};
String[] arr2 = new String[]{"111", "222", "333"}; System.out.println(Arrays.asList(arr1)); System.out.println(Arrays.asList(arr2));
輸出:

[[[email protected]]
[111, 222, 333]

驗證:

int[] arr1 = new int[]{111, 222, 333};List list = Arrays.asList(arr1);
System.out.println("list.size() = " + list.size());
int[] arr3 = (int[]) list.get(0); System.out.println(Arrays.toString(arr3));

利用1.8特性,也是可以實現轉換的:

int[] arr1 = {111, 222, 333};
List<Integer> list = IntStream.of(arr1).boxed().collect(Collectors.toList());
list.forEach(System.out::println);

asList

public static <T> List<T> asList(T... a)
返回一個受指定陣列支援的固定大小的列表。(對返回列表的更改會“直接寫”到陣列。)此方法同 Collection.toArray() 一起,充當了基於陣列的 API 與基於 collection 的 API 之間的橋樑。返回的列表是可序列化的,並且實現了RandomAccess

此方法還提供了一個建立固定長度的列表的便捷方法,該列表被初始化為包含多個元素:

     List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
 
引數:
a - 支援列表的陣列。
返回:
指定陣列的列表檢視。

利用Arrays.asList(array)將返回一個List(列表檢視),然而這個返回的List並不支援add和remove的操作。

有個很有意思的tip:<T>與T的區別?

其實和變數先宣告再使用本質上是相同的。

返回的List是在Arrays內部定義的:

private static class ArrayList<E> extends AbstractList<E>
    implements RandomAccess, java.io.Serializable
{...}

在AbstractList中檢視add和remove方法:

public void add(int index, E element) {
    throw new UnsupportedOperationException();
}
public E remove(int index) {
    throw new UnsupportedOperationException();
}
所以,當我們對Arrays.asList返回的List進行新增或刪除時將會報 java.lang.UnsupportedOperationException 異常。

如果想執行新增/刪除操作,我們可以以此建立新的List

String[] arr1 = {"111", "222", "333"};
List<String> list = new ArrayList<>(Arrays.asList(arr1));
list.add("444");
list.forEach(System.out::println);

而當我們對其中一個做更新操作時,另一個會同時更新。這是檢視的特性

String[] arr1 = {"111", "222", "333"};
List<String> list = Arrays.asList(arr1);
arr1[0] = "11";
list.set(1, "22");
list.forEach(s -> System.out.print(s + " "));
System.out.println("\n" + Arrays.toString(arr1));
輸出:

11 22 333 
[11, 22, 333]

集合轉化為陣列

使用集合中的toArray方法可以實現以上目的。 List集合中toArray的兩個方法:
Object[] toArray();
<T> T[] toArray(T[] a);
但是我們卻不能這樣使用:
List<String> list = new ArrayList<>();
list.add("111");
list.add("222");
list.add("333");
list.forEach(System.out::println);
String[] arr = (String[]) list.toArray();
會報ClassCastException異常。 實際上,必須使用toArray方法的一個變體形式。
List<String> list = new ArrayList<>();
list.add("111");
list.add("222");
list.add("333");
list.forEach(System.out::println);
String[] arr = list.toArray(new String[0]);
System.out.println(Arrays.toString(arr));
這樣一來,返回的陣列就會建立為相同的陣列型別。(toArray(new String[x]),x小於size則建立新的陣列並返回,大於等於則返回你建立的,當然大於的那一部分初始化null)
String[] arr = list.toArray(new String[list.size()]);
在這種情況下,不會建立新陣列。 當然,也可以這樣:
String[] arr1 = Arrays.copyOf(list.toArray(), list.size(), String[].class);
System.out.println(Arrays.toString(arr1));
有點曲線救國的味道。

toArray

Object[] toArray()
返回包含此 collection 中所有元素的陣列。如果 collection 對其迭代器返回的元素順序做出了某些保證,那麼此方法必須以相同的順序返回這些元素。

返回的陣列將是“安全的”,因為此 collection 並不維護對返回陣列的任何引用。(換句話說,即使 collection 受到陣列的支援,此方法也必須分配一個新的陣列)。因此,呼叫者可以隨意修改返回的陣列。

此方法充當了基於陣列的 API 與基於 collection 的 API 之間的橋樑。

返回:
包含此 collection 中所有元素的陣列

toArray

<T> T[] toArray(T[] a)
返回包含此 collection 中所有元素的陣列;返回陣列的執行時型別與指定陣列的執行時型別相同。如果指定的陣列能容納該 collection,則返回包含此 collection 元素的陣列。否則,將分配一個具有指定陣列的執行時型別和此 collection 大小的新陣列。

如果指定的陣列能容納 collection,並有剩餘空間(即陣列的元素比 collection 的元素多),那麼會將陣列中緊接 collection 尾部的元素設定為null。(只有 在呼叫者知道此 collection 沒有包含任何 null 元素時才能用此方法確定 collection 的長度。)

如果此 collection 對其迭代器返回的元素順序做出了某些保證,那麼此方法必須以相同的順序返回這些元素。

toArray() 方法一樣,此方法充當基於陣列的 API 與基於 collection 的 API 之間的橋樑。更進一步說,此方法允許對輸出陣列的執行時型別進行精確控制,並且在某些情況下,可以用來節省分配開銷。

假定 x 是隻包含字串的一個已知 collection。以下程式碼用來將 collection 轉儲到一個新分配的 String 陣列:

     String[] y = x.toArray(new String[0]); 
注意,toArray(new Object[0])toArray() 在功能上是相同的。
引數:
a - 儲存此 collection 元素的陣列(如果其足夠大);否則,將為此分配一個具有相同執行時型別的新陣列。
返回:
包含此 collection 中所有元素的陣列
丟擲:
- 如果指定陣列的執行時型別不是此 collection 每個元素執行時型別的超型別