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 接口就能夠用到了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。