好的,阿杰,我们来详细讲讲 Java 8map()flatMap() 的用法与区别。
这两个方法常见于 Stream APIOptional、以及 Optional 等场景中,是 Java 函数式编程的核心操作之一。


🧩 一、map() 的基本用法

map()一对一映射操作:
对流(Stream)中的每个元素应用一个函数,然后将结果收集成一个新的流。

✅ 示例 1:基本类型映射

import java.util.*;
import java.util.stream.*;

public class MapExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Tom", "Jerry", "Spike");

        // map():将每个字符串转成大写
        List<String> upperNames = names.stream()
                                       .map(String::toUpperCase)
                                       .collect(Collectors.toList());

        System.out.println(upperNames); // [TOM, JERRY, SPIKE]
    }
}

👉 map() 的返回结果与输入元素数量一致,只是值被转换


🌊 二、flatMap() 的基本用法

flatMap()一对多映射 + 扁平化(flatten) 操作:
当你的映射函数返回的是一个 Stream(或集合) 时,flatMap() 会把嵌套的结构“打平”。

✅ 示例 2:List<List> 扁平化

import java.util.*;
import java.util.stream.*;

public class FlatMapExample {
    public static void main(String[] args) {
        List&lt;List&lt;String>> listOfLists = Arrays.asList(
            Arrays.asList("Java", "Python"),
            Arrays.asList("C++", "Go")
        );

        // flatMap():打平嵌套结构
        List&lt;String> languages = listOfLists.stream()
                                            .flatMap(List::stream)
                                            .collect(Collectors.toList());

        System.out.println(languages); // [Java, Python, C++, Go]
    }
}

👉 flatMap() 会先把每个子列表变成流 (List::stream),再把所有小流合并成一个大流。


🧠 三、对比总结

方法主要作用函数返回类型输出结构
map()一对一映射任意类型 RStream<R>
flatMap()一对多映射 + 扁平化Stream<R>Stream<R>(打平嵌套结构)

✅ 示例 3:区别对比

List&lt;String> words = Arrays.asList("hello", "world");

// map:得到 Stream&lt;Stream&lt;String>>
List&lt;Stream&lt;String>> mapped = words.stream()
                                   .map(word -> Arrays.stream(word.split("")))
                                   .collect(Collectors.toList());

// flatMap:得到 Stream&lt;String>
List&lt;String> flatMapped = words.stream()
                               .flatMap(word -> Arrays.stream(word.split("")))
                               .collect(Collectors.toList());

System.out.println(mapped);    // [[h, e, l, l, o], [w, o, r, l, d]] (嵌套流)
System.out.println(flatMapped); // [h, e, l, l, o, w, o, r, l, d]


💡 四、在 Optional 中的应用

示例 4:map() vs flatMap() in Optional

Optional&lt;String> name = Optional.of("Tom");

// map: 返回 Optional&lt;Optional&lt;Integer>> ❌
Optional&lt;Optional&lt;Integer>> wrong = name.map(n -> Optional.of(n.length()));

// flatMap: 返回 Optional&lt;Integer> ✅
Optional&lt;Integer> correct = name.flatMap(n -> Optional.of(n.length()));

System.out.println(correct.get()); // 3


📦 五、常见应用场景

场景用法
集合嵌套(List<List>)flatMap 打平
Optional 嵌套(Optional<Optional>)flatMap 去除嵌套
文本拆分(String → 单词列表)flatMap(str -> Arrays.stream(str.split(" ")))
复杂对象映射(如 List<User> → 所有 UseraddressListusers.stream().flatMap(u -> u.getAddresses().stream())