最近在 leetcode 刷題的時候遇到過好幾次這樣的情況:需要返回的數據類型是數組(Arrays
),但是求解的時候並不知道數組的長度,這時候就需要先用 List
進行臨時存儲,最后再轉化為 Arrays
返回。所以這里將 java 中 Arrays
和 List
之間的轉化總結一下。
Arrays
轉為 List
1. 利用Arrays.asList()
方法
Arrays
類提供了 asList()
方法,我們先來看看源碼:
可以看到,Arrays.asList()
是泛型方法,傳入的必須是對象數組而不是基本數據類型的數組。首先拿 String
數組來看一下:
沒有問題,數組“變成了” List
,並且可以通過List
的 get()
方法進行元素訪問。但是換成 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
的修改方法例如add
、remove
等。因此對於轉化后的List對象如果進行修改會報異常!!
2. 使用 Java8 的Stream
接口
挖完坑之后當然是要填坑了。其實自己實現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]);
像這樣就沒問題,但是對於基本數據類型像char
、int
這樣就會報錯,必須指定為對應的包裝類才可以。因此即使是 <T> T[] toArray(T[] a)
這個方法,也無法直接將Integer
的列表轉化為int[]
數組。
2. 使用 Java8 的Stream
接口
以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
類型,最后通過Stream
的 toArray
方法轉化為數組。其中mapToInt()
參數為給定的映射函數,這里表示映射到int
類型。::
也是java8中的操作符,表示對Integer
類的intValue()
方法的調用,更多的使用方式可以看官方文檔。
總結
Java集合中只能存放引用類型的數據,不能存放基本數據類型,因此在對基本數據類型數據進行“Arrays-to-List”或者“List-to-Arrays”操作的時候,類本身的方法可能不適用,這時候就必須手動遍歷轉化,或者利用Java8的Stream
接口幫助實現。上面的實現看起來好像是把簡單問題變復雜了,確實在進行簡單轉化的時候遍歷復制元素是最方便的,但是Stream
接口還有一些強大的功能,如果轉化過程中還有一些復雜操作像元素篩選、過濾等 Stream
接口就能夠用到了。