1. 程式人生 > 實用技巧 >Java Arrays 和 List的相互轉化

Java Arrays 和 List的相互轉化

最近在 leetcode 刷題的時候遇到過好幾次這樣的情況:需要返回的資料型別是陣列(Arrays),但是求解的時候並不知道陣列的長度,這時候就需要先用 List 進行臨時儲存,最後再轉化為 Arrays 返回。所以這裡將 java 中 ArraysList 之間的轉化總結一下。

Arrays 轉為 List

1. 利用Arrays.asList() 方法

Arrays類提供了 asList() 方法,我們先來看看原始碼:

可以看到,Arrays.asList() 是泛型方法,傳入的必須是物件陣列而不是基本資料型別的陣列。首先拿 String 陣列來看一下:

沒有問題,陣列“變成了” List

,並且可以通過Listget() 方法進行元素訪問。但是換成 int[] 陣列呢?

Eclipse提示出錯了,需要將 List 的元素型別換成 int[],也就是說對於基本資料型別的陣列,Arrays.asList() 會將整個陣列作為一個最後返回的列表中的一個物件。不信的話就改成 int[] 試一下,看結果:

所以,對於基本資料型別的陣列,是不能用 Arrays.asList() 將其轉化為 List的。

另一個坑
是不是以為對於物件陣列,Arrays.asList()就可以無腦使用了呢?還是圖樣圖森破啊。再看看原始碼:

發現了吧!Arrays.asList()這裡返回的ArrayList

並不是java.util.ArrayList,而是java.util.Arrays自己定義的一個靜態內部類,這個內部類繼承了AbstarctList類。並且,這個自定義的內部類並沒有實現java.util.List 的修改方法例如addremove。因此對於轉化後的List物件如果進行修改會報異常!!

2. 使用 Java8Stream介面

挖完坑之後當然是要填坑了。其實自己實現Arrays 轉為 List最簡單的就是遍歷添加了,不用多說。這裡說一個Java8以上版本中的高階操作——Stream介面,這個介面主要就是用來支援對元素流的函式式操作,更詳細的介紹可以參考官方文件。先給出轉化程式碼:

public static void main(String[] args) {
    int[] arr = {1, 2, 3};
    List<Integer> ls =  Arrays.stream(arr).boxed().collect(Collectors.toList());
    System.out.println(ls.get(0));
}

上面程式碼得到的 ls 支援列表的元素操作函式。Arrays.stream() 函式返回一個IntStream物件(儲存原始int型別的Stream),boxed()函式是 IntStream 物件的裝箱函式,返回Stream<Integer>物件。collect()函式根據指定的Collector 對流元素進行對應操作,上面程式碼中 Collectors.toList() 返回一個將所有元素收集到一個 List中的 Collector

List 轉為 Arrays

1. 使用 List.toArray()方法

List 有兩個toArray()方法,其中無參的toArray()方法返回的是Object[]陣列,也無法通過強制型別轉換轉換成別的型別(所以不明白無參的這個方法應用場景在哪裡)。此外還有一個有參的泛型方法 <T> T[] toArray(T[] a),這個方法可以返回指定型別的陣列,但是也只能是引用型別:

List<String> ls = new ArrayList<>();
ls.add("java");
ls.add("python");
ls.add("php");
String[] arr = ls.toArray(new String[0]);
System.out.println(arr[1]);

像這樣就沒問題,但是對於基本資料型別像charint這樣就會報錯,必須指定為對應的包裝類才可以。因此即使是 <T> T[] toArray(T[] a)這個方法,也無法直接將Integer的列表轉化為int[]陣列。

2. 使用 Java8Stream介面

List<Integer>int[]為例,下面這段程式碼就可以實現轉化:

List<Integer> ls = new ArrayList<>();
ls.add(1);
ls.add(3);
ls.add(4);
int[] arr = ls.stream().mapToInt(Integer::intValue).toArray();
System.out.println(arr[1]);

首先通過stream()方法將列表轉化為流物件,再通過mapToInt()函式將流物件中的元素對映成int型別,最後通過StreamtoArray方法轉化為陣列。其中mapToInt() 引數為給定的對映函式,這裡表示對映到int型別。::也是java8中的操作符,表示對Integer類的intValue()方法的呼叫,更多的使用方式可以看官方文件

總結

Java集合中只能存放引用型別的資料,不能存放基本資料型別,因此在對基本資料型別資料進行“Arrays-to-List”或者“List-to-Arrays”操作的時候,類本身的方法可能不適用,這時候就必須手動遍歷轉化,或者利用Java8的Stream介面幫助實現。上面的實現看起來好像是把簡單問題變複雜了,確實在進行簡單轉化的時候遍歷複製元素是最方便的,但是Stream介面還有一些強大的功能,如果轉化過程中還有一些複雜操作像元素篩選、過濾等 Stream 介面就能夠用到了。