Flink 核心算子详解:map / flatMap / filter / process

文章目录

在学习 Flink 的过程中,mapflatMapfilterprocess 是最常用、也是最容易让人迷糊的几个算子。

很多初学者都会有这些疑问:

  • 为什么 flatMap 里一定要写 Collector
  • 为什么 map 不能返回多个元素?
  • process 到底强在哪里?什么时候该用?

本文将 从接口设计出发 ,结合 可运行 Demo + 实际运行结果,带你真正理解 Flink 算子的设计思想。


一、算子能力对照表

算子 输入 → 输出 是否可丢数据 是否可多输出 是否可用时间/状态
map 1 → 1
filter 1 → 0/1
flatMap 1 → 0/N
process 1 → 0/N

一句话总结:

越简单的算子,约束越多,Flink 能优化得越好;
越底层的算子,能力越强,但责任全在你。


二、测试数据

text 复制代码
hello flink
hello world

三、map:一进一出

1. 接口定义

java 复制代码
public interface MapFunction<T, R> {
    R map(T value) throws Exception;
}

特点:

  • 一个输入
  • 必须返回一个输出
  • 不能多、不能少

2. Demo:字符串转大写

java 复制代码
  StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        DataStream<String> source = env.fromElements(
                "hello flink",
                "hello world"
        );

        source.map(value -> value.toUpperCase()).print();
        try {
            env.execute("Simple Map Example");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

DataStream 程序是惰性执行的,必须调用 execute() 才会触发作业执行

3. 运行结果

text 复制代码
8> HELLO WORLD
7> HELLO FLINK

四、filter:只负责"要不要"

1. 接口定义

java 复制代码
public interface FilterFunction<T> {
    boolean filter(T value) throws Exception;
}

注意:

  • 不能修改数据
  • 只能决定保留 or 丢弃

2. Demo:只保留包含 flink 的行

java 复制代码
source
    .filter(line -> line.contains("flink"))
    .print();

3. 运行结果

text 复制代码
6> hello flink

五、flatMap:一进多出

1. 接口定义

java 复制代码
public interface FlatMapFunction<T, O> {
    void flatMap(T value, Collector<O> out) throws Exception;
}

2. 为什么要 Collector

因为:

flatMap 允许一条输入,输出 0 条、1 条或多条数据

返回值已经不够用,所以 Flink 把"输出控制权"交给你。


3. Demo:拆分单词

java 复制代码
        source.flatMap((String line, Collector<String> out) -> {
                    for (String word : line.split(" ")) {
                        out.collect(word);
                    }
                })
                .returns(Types.STRING)   // ⭐ 关键:补全类型信息
                .print();

4. 运行结果

text 复制代码
4> hello
4> world
3> hello
3> flink

六、process:最底层、最强大的算子

map / filter / flatMap 能做的,process 全都能做

并且还能:

  • 获取时间
  • 使用状态
  • 注册定时器

1. 接口结构

java 复制代码
public abstract class ProcessFunction<I, O> {
    public abstract void processElement(
        I value,
        Context ctx,
        Collector<O> out
    ) throws Exception;
}

2. Demo:手写 WordCount(不使用 keyBy.sum)

java 复制代码
      source
                .keyBy(value -> value)
                .process(new ProcessFunction<String, Tuple2<String, Integer>>() {

                    private int count = 0;

                    @Override
                    public void processElement(
                            String value,
                            Context ctx,
                            Collector<Tuple2<String, Integer>> out) {

                        count++;
                        out.collect(Tuple2.of(value, count));
                    }
                })
                .print();

3. 运行结果

text 复制代码
3> (hello flink,1)
6> (hello world,1)

⚠️ 注意:这里只是演示 process 能力

实际生产应使用 Keyed State 而不是普通成员变量


七、如何选择算子?

官方推荐原则:

能用 map,就别用 flatMap
能用 flatMap,就别用 process

原因是:

  • 简单算子 → Flink 能做更多优化
  • process → 灵活但难维护、难调优

八、总结

  • map:最简单,1 → 1
  • filter:只做判断
  • flatMap:拆分、多输出
  • process:终极武器,慎用

理解算子 ≠ 记 API
理解算子 = 理解接口设计 + 数据流模型

相关推荐
不知名的老吴几秒前
后端知识点:Python处理加权点赞
开发语言·python
忡黑梨4 分钟前
eNSP_从直连到BGP全网互通
c语言·网络·数据结构·python·算法·网络安全
瑞华丽PLM9 分钟前
传统研发协同低效痛点待解,PLM 系统数字化选型助力研发效率提升与转型
大数据·plm·国产plm·瑞华丽plm·瑞华丽
Cyber4K18 分钟前
【Python专项】基础语法(2)
开发语言·python
乐迪信息20 分钟前
乐迪信息:实时预警,秒级响应:船舶AI异常行为检测算法
大数据·人工智能·算法·安全·目标跟踪
红色星际22 分钟前
进军具身机器人和Robotaxi的智驾公司
大数据·人工智能·机器人
Bruce_Liuxiaowei23 分钟前
《轻量化制播系统技术应用指南(2026版)》解读:县级融媒体的“减负增效“新路径
大数据·人工智能·媒体
2601_9561394231 分钟前
文旅行业品牌全案公司哪家强
大数据·人工智能·python
生活观察站31 分钟前
中文在线亮相横琴—澳门国际数字艺术博览会国际数字创意论坛:AI漫剧打开内容创作新想象
大数据·人工智能
hrhcode32 分钟前
【LangGraph】二.State 和 Node 的设计细节
python·ai·langchain·langgraph·ai框架