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 每個元素執行時型別的超型別