Java 中的 flatMap

Mohammad Irfan 2023年1月30日 2022年4月26日
  1. Java 中的 flatMap 函式
  2. 在 Java 中如何使用 flatMap() 方法
  3. 從 Java 中的 flatMap 中刪除重複項
  4. 在 Java 中過濾 flatMap 元素
  5. flatMap 和原始型別
  6. まとめ
Java 中的 flatMap

本教程介紹 flatMap 以及如何在 Java 中使用它。

flatMap 是 Java 流中的一個操作/函式,用於在執行某些功能性任務後獲取新流。在這裡,我們將討論 flatMap() 操作。

此操作是 map() 操作的擴充套件。此函式應用於每個流元素並生成新值流。

然後將這些新流的生成元素複製到最近建立的流中,該流用作方法的返回值。

Java 中的 flatMap 函式

flatMap() 函式的簽名是:

<R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)

flatMap 是一箇中間操作。中間操作是惰性操作,在 Stream 例項上呼叫,在它們完成處理後,它們返回一個 Stream 例項。

flatMap() 操作是 map()flat() 操作的組合。這意味著 flatMap() 操作首先應用 map() 操作,然後將結果展平。

此方法採用對映器,該函式將應用於傳入的 Stream 的每個元素。

Java 中的扁平化

我們先來了解一下什麼是扁平化。展平列表會將兩個或多個級別列表轉換為單個級別列表。

兩個 2 級列表的示例是:

[["I"], ["Love"], ["Delft", "Stack"]]

扁平化後的上述列表轉換為:

["I", "Love", "Delft", "Stack"]

生成的列表是單級列表。

扁平化列表的必要性

有必要對一個列表進行扁平化處理,因為處理幾個 Stream 級別是很困難、很複雜、很容易出錯的。

我們可以使用 Stream.flatMap() 操作將兩個 Stream 級別轉換為單個級別 Stream。我們將在本文後面使用一個示例來理解這一點。

在 Java 中如何使用 flatMap() 方法

在這個例子中,我們首先使用 stream() 方法從 List 建立了一個物件流。每個物件都是公司的程式設計師。

我們將首先建立一個類來代表公司中的開發人員/程式設計師。

import java.util.HashSet;
import java.util.Set;
class Programmer{
    private String name;
    private Set<String> languages_known;

    public Programmer(String name){
        this.name = name;
        this.languages_known = new HashSet<>();
    }

    public void addLanguage(String lang){
        this.languages_known.add(lang);
    }

    public Set<String> getLanguages(){
        return languages_known;
    }
}

我們現在將初始化物件並建立一個列表列表,其中包含整個公司程式設計師已知的所有語言。然後,我們將扁平化該列表以瞭解團隊中的所有語言。

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class SimpleTesting{
    public static void main(String[] args) {
        Programmer raj = new Programmer("Raj");
        raj.addLanguage("Java");
        raj.addLanguage("Dart");
        raj.addLanguage("go");
        raj.addLanguage("groovy");
        
        Programmer karan = new Programmer("Karan");
        karan.addLanguage("Java");
        karan.addLanguage("Python");

        Programmer chahal = new Programmer("Chahal");
        chahal.addLanguage("Dart");
        chahal.addLanguage("Javascript");

        List<Programmer> team = new ArrayList<>();
        team.add(raj);
        team.add(karan);
        team.add(chahal);

        System.out.println("Programming languages in the team: ");
        List<String> languages = team.stream().map(Programmer::getLanguages).flatMap(Collection::stream).collect(Collectors.toList());
        System.out.println(languages);
    }
}

輸出:

Programming languages in the team: 
[Java, groovy, go, Dart, Java, Python, Javascript, Dart]

在上面的示例中,我們首先使用流 API 建立了所有程式設計師的流。之後,我們使用 map() 函式建立了每個程式設計師都知道的語言列表流。

從 Java 中的 flatMap 中刪除重複項

然後我們使用 flatMap() 操作展平這個列表,並將結果流轉換為一個列表。請注意,生成的 List 有一些重複值;我們使用 duplicate() 操作來消除這些。

看看下面的程式碼。

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class SimpleTesting{
    public static void main(String[] args) {
        Programmer raj = new Programmer("Raj");
        raj.addLanguage("Java");
        raj.addLanguage("Dart");
        raj.addLanguage("go");
        raj.addLanguage("groovy");
        Programmer karan = new Programmer("Karan");
        karan.addLanguage("Java");
        karan.addLanguage("Python");
        Programmer chahal = new Programmer("Chahal");
        chahal.addLanguage("Dart");
        chahal.addLanguage("Javascript");
        List<Programmer> team = new ArrayList<>();
        team.add(raj);
        team.add(karan);
        team.add(chahal);
        System.out.println("Programming languages in the team: ");
        List<String> languages = team.stream()
                                    .map(Programmer::getLanguages)
                                    .flatMap(Collection::stream)
                                    .distinct()
                                    .collect(Collectors.toList());
        System.out.println(languages);
    }
}

輸出:

Programming languages in the team: 
[Java, groovy, go, Dart, Python, Javascript]

在 Java 中過濾 flatMap 元素

如果我們想要獲取除 Dart 之外的所有語言,我們可以使用 filter() 函式和 flatMap()。看看下面的程式碼。

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class SimpleTesting{
    public static void main(String[] args) {
        Programmer raj = new Programmer("Raj");
        raj.addLanguage("Java");
        raj.addLanguage("Dart");
        raj.addLanguage("go");
        raj.addLanguage("groovy");
        Programmer karan = new Programmer("Karan");
        karan.addLanguage("Java");
        karan.addLanguage("Python");
        Programmer chahal = new Programmer("Chahal");
        chahal.addLanguage("Dart");
        chahal.addLanguage("Javascript");
        List<Programmer> team = new ArrayList<>();
        team.add(raj);
        team.add(karan);
        team.add(chahal);
        System.out.println("Programming languages in the team: ");
        List<String> languages = team.stream()
                                    .map(Programmer::getLanguages)
                                    .flatMap(Collection::stream)
                                    .distinct()
                                    .filter(x -> !x.equals("Dart"))
                                    .collect(Collectors.toList());
        System.out.println(languages);
    }
}

輸出:

Programming languages in the team:
[Java, groovy, go, Python, Javascript]

flatMap 和原始型別

Java Stream API 還為原始資料型別(如 int、float、long)提供了單獨的操作,如 flatMapto{primitive type} 以扁平化原始型別的 Stream。

import java.util.Arrays;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class SimpleTesting{
    public static void main(String[] args) {
        int[] Je_array= {3,5,2,35,85,32,23,43,12};
        Stream<int[]> JE_streamArray = Stream.of(Je_array);
        IntStream JE_intStream = JE_streamArray.flatMapToInt(x -> Arrays.stream(x));
        JE_intStream.forEach(x -> System.out.println(x));
    }
}

輸出:

3
5
2
35
85
32
23
43
12

まとめ

我們已經討論了 flatMap() 操作以及為什麼需要它。我們還討論了 Java Stream API 如何為原始資料型別提供單獨的 flatMap() 操作。

請注意,普通的 flatMap() 操作也適用於原始資料型別。

相關文章 - Java Stream