使用 flatMap() 將巢狀的列表合併成一個新的列表

木头左發表於2024-04-07

flatMap() 是Java 8中Stream API中的一箇中間操作,用於將巢狀集合的元素合併成一個扁平化的流,其中每個元素都是由巢狀集合中的元素組成的。

flatMap() 方法的語法如下:<R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)

其中,mapper 是將元素對映為流的一個函式。

下面是一個使用 flatMap() 操作的例子。假設有一個列表 List<List<String>> nestedList,它包含多個列表,每個列表又包含多個字串。我們可以使用 flatMap() 方法將所有字串合併成一個扁平的流:

List<String> flatList = nestedList.stream()
                                  .flatMap(childList -> childList.stream())
                                  .collect(Collectors.toList());

在上面的程式碼中,我們將 nestedList 轉換為一個流,並使用 flatMap() 操作將每個子列表轉換為一個子流。最後,我們將所有子流合併成一個扁平流,並將其收集到一個列表中。

需要注意的是,flatMap() 操作會返回一個新的 Stream 流物件,它並不會修改原來的流。因此,如果要將流進行多次扁平化,需要使用多個 flatMap() 操作或巢狀多個 flatMap() 操作。

flatMap() 是一個非常有用的中間操作,可以用於扁平化巢狀的集合,便於進行後續的資料處理。在實際開發中,我們可以將其用於各種場景,如樹形結構資料的扁平化、多個集合的合併等等。

以下舉例來說明,processNodeList 是一個 List<String> 型別的資料列表。接下來,我們對每個元素執行 map() 操作,將其轉換為另一個 List 型別的資料列表。然後我們使用 flatMap() 將巢狀的列表合併成一個新的列表。

錯誤程式碼:

List processNodeId = Arrays.asList(processNodeList.stream() .map(item -> item.getProcessNodeList()) .flatMap(Arrays::stream) .toArray(String[]::new));

雖然這段程式碼使用了Java 8中的 Stream API,但它存在一些缺陷和可以改進的地方。以下是幾個可能的問題:

  • 列表型別轉換問題:在 map() 操作中,我們將一個 String 型別的元素對映到一個 List<String> 型別的列表。這可能會導致型別轉換異常或不必要的記憶體消耗。
  • 重複的型別轉換:在 flatMap() 操作中,我們將巢狀的列表轉換為一個扁平的列表,但是我們使用了兩次同樣型別的轉換操作。這可能會導致不必要的效能開銷。
  • 不必要的陣列轉換:在 toArray() 操作中,我們將列表轉換為一個新的 String[] 陣列型別,以便將其新增到 filterParams 物件中。然而,這樣的轉換可能會導致不必要的記憶體開銷和型別轉換。

為了改進這段程式碼,我們可以使用以下方法:

  • 改變對映邏輯:我們可以改變 map() 操作,避免將元素對映到一個巢狀列表型別。例如,我們可以使用 map() 將列表中的元素對映到它們的 processNodeList 屬性,然後使用 flatMap() 合併所有的列表元素。
  • 避免重複型別轉換:我們可以使用 flatMap() 操作一次轉換巢狀的列表,並將其轉換為一個 Stream<String> 流,潔簡流程。
  • 避免不必要的陣列轉換:我們可以將流直接轉換為 List<String> 型別,而不必先將其轉換為 String[] 陣列型別再將其新增到 filterParams 物件中。

改進後的程式碼如下:

List<String> processNodeId = processNodeList.stream()
        .flatMap(item -> Arrays.stream(item.getProcessNodeList()))
        .collect(Collectors.toList());```







![](https://mutouzuo.oss-cn-hangzhou.aliyuncs.com/my/mudouzuo1.png)

相關文章