Java Stream轉List的幾種方法

語言: CN / TW / HK

前幾天分享了 如何優雅的除錯Java Stream操作 。然後有小夥伴對其中的一段程式碼有一些疑問:“為啥你的stream可以直接toList而不必collect?” 下面就給大家解讀下這個內容。

疑問的程式碼片段如下:

public class StreamTest {

    @Test
    void test() {
        List<String> list = List.of("blog.didispace.com", "spring4all.com", "openwrite.cn", "www.didispace.com");

        List<String> result = list.stream()
                .filter(e -> e.contains("didispace.com"))
                .filter(e -> e.length() > 17)
                .toList();

        System.out.println(result);
    }

}

小夥伴疑問的就是第10行: toList() 。實際上這個方法是Java 16才支援的一個方法,它可以直接將 Stream 轉化成 List 。而因為目前很多小夥伴還在用Java 8,所以在介紹如何除錯Stream的時候,直接用我這段程式碼可能會碰到這個問題。

那麼Java 8的使用者怎麼寫呢?我看到也有網友直接給出了Java 8下的方法,就如下面這樣:

List<String> result = list.stream()
    .filter(e -> e.contains("didispace.com"))
    .filter(e -> e.length() > 17)
    .collect(Collectors.toList());

Stream.toList() 和 Stream.collect(Collectors.toList()) 的區別

就完整上面的程式碼邏輯,這樣的替換完全是可以的,但是雖然最終都轉成List了,他們之間是否還有區別呢?

這裡我單獨拉出來說,顯然肯定是有區別的。

通過檢視 Stream.toList() 的原始碼:

default List<T> toList() {
    return (List<T>) Collections.unmodifiableList(new ArrayList<>(Arrays.asList(this.toArray())));
}

我們可以發現,它所建立的是一個 unmodifiableList 不可變的List。

而使用 Stream.collect(Collectors.toList()) 創建出來的則是一個普通的List,是可以做增刪改操作的。

那麼如果在Java 8中也要建立不可變的List要怎麼寫呢?其實也很簡單,只需要呼叫 Collectors.toUnmodifiableList() 就可以了。

所以與本文開頭等價的Java 8程式碼替換應該這樣寫:

List<String> result = list.stream()
    .filter(e -> e.contains("didispace.com"))
    .filter(e -> e.length() > 17)
    .collect(Collectors.toUnmodifiableList());

好了,今天的分享就到這裡,你學會了嗎?

本期影片: https://www.bilibili.com/video/BV16Y411F7Pm/

如果您學習過程中如遇困難?可以加入我們超高質量的技術交流群,參與交流與討論,更好的學習與進步!另外,不要走開,關注我,持續更新Java新特性專欄!