map与flatMap

flatMap参数必须是一个个流,作用是将多个流合并成一个流

package chapter1;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.stream.Stream;

public class IO {
    public static void main(String[] args) throws IOException {
        long uniqueWords = 0;
        try (Stream<String> lines = Files.lines(Paths.get("src/main/resources/data.txt"))) {
            /** map */
//            Stream<String[]> stream1 = lines.map(line -> line.split(" "));
            /** flatMap */
            Stream<String> stringStream = lines.flatMap(line -> {
                Stream<String> stream = Arrays.stream(line.split(" "));
                return stream;
            });
            uniqueWords = stringStream.distinct().count();
        }
        System.out.println(uniqueWords);//4
    }
}
data.txt:

a b b c
c
d a
<think>好的,用户想了解Java Stream API中mapflatMap的区别和用法。首先我需要回忆一下这两个方法的作用。 记得map方法是将流中的每个元素映射为另一个元素,一对一的关系。比如,将字符串转换为它的长度,每个输入元素对应一个输出元素。而flatMap则是处理每个元素并生成一个新的流,然后把所有流合并成一个流,也就是一对多的情况。例如,将一个包含句子的流拆分成单词流,每个句子可能对应多个单词。 接下来,我需要参考提供的资料来确认是否正确。引用[2]中提到flatMap可以将句子拆分为单词,然后处理每个单词的长度,这说明flatMap确实用于一对多的场景。而引用[3]指出,map是映射成一个数据节点,flatMap映射成一个数据流,可能多个节点。这进一步验证了我的理解。 用户可能需要具体的例子来理解两者的区别。例如,使用map处理字符串列表,每个字符串转为大写,而flatMap处理包含多个句子的列表,拆分成单词。这样对比会更清晰。 另外,要注意两者的返回值不同。map的参数是Function,返回的是单个对象,而flatMap需要返回Stream实例。这点需要明确说明,避免混淆。 还需要提到应用场景,比如当需要将嵌套结构扁平化时,比如List<List<String>>转成List<String>,这时候用flatMap更合适。而单纯的元素转换用map。 总结下来,回答的结构应该是先分别介绍mapflatMap,再比较它们的区别,给出示例代码,最后说明适用场景。确保引用正确的资料,比如引用[2]和[3]中的例子和解释,这样回答更有依据。</think>### Java StreammapflatMap的区别及用法解析 #### 一、核心功能对比 1. **map操作** - 实现**一对一映射**,对每个元素应用转换函数生成新元素 - 输入输出保持**元素数量一致** - 语法:`<R> Stream<R> map(Function<? super T, ? extends R> mapper)` 示例:字符串转大写 ```java List<String> words = Arrays.asList("apple", "banana"); List<String> upperCase = words.stream() .map(String::toUpperCase) .collect(Collectors.toList()); // 输出[APPLE, BANANA] ``` 2. **flatMap操作** - 实现**一对多映射**,将每个元素转换为新流后进行**扁平化合并** - 输入输出**元素数量可变** - 语法:`<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)` 示例:拆分句子为单词 ```java List<String> sentences = Arrays.asList("Hello World", "Java Stream"); List<String> words = sentences.stream() .flatMap(str -> Arrays.stream(str.split(" "))) .collect(Collectors.toList()); // 输出[Hello, World, Java, Stream] ``` #### 二、关键差异对比 | 特性 | map | flatMap | |---------------------|------------------------------|------------------------------| | 返回值要求 | 任意类型对象 | 必须返回Stream实例 | | 元素数量 | 保持1:1对应 | 允许1:N转换 | | 数据结构处理 | 单层转换 | 可展平嵌套结构 | | 典型应用场景 | 简单类型转换 | 集合展开/多维结构扁平化 | #### 三、使用场景对比 1. **map适用场景** - 数据格式转换:`String → Integer` - 属性提取:对象集合中获取特定字段 - 简单计算:数值型数据的算术运算 示例:提取字符串长度 ```java List<Integer> lengths = words.stream() .map(String::length) .collect(Collectors.toList()); ``` 2. **flatMap适用场景** - 嵌套集合展平:`List<List<T>> → List<T>` - 多层级数据处理:日志行拆分为单词 - 关联数据合并:多个数据源的流合并 示例:二维数组扁平化 ```java List<List<Integer>> matrix = Arrays.asList( Arrays.asList(1,2), Arrays.asList(3,4) ); List<Integer> flatList = matrix.stream() .flatMap(List::stream) .collect(Collectors.toList()); // 输出[1,2,3,4] ``` #### 四、性能注意事项 1. 优先使用map进行简单转换,时间复杂度为$O(n)$ 2. flatMap会产生额外创建流的开销,时间复杂度可能达到$O(n*m)$(m为嵌套元素数量) 3. 对于复杂嵌套结构,flatMap比嵌套循环更高效[^3] #### 五、高级用法示例 文件读取后统计词频 ```java Files.lines(Paths.get("data.txt")) .flatMap(line -> Arrays.stream(line.split("\\W+"))) .filter(word -> !word.isEmpty()) .collect(Collectors.groupingBy( String::toLowerCase, Collectors.counting() )); ``` 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值