flink 常用算子之map、filter和flatMap

Transformation各算子可以对Flink数据流进行处理和转化,是Flink流处理非常核心的API。

map

map算子对一个DataStream中的每个元素使用用户自定义的map函数进行处理,每个输入元素对应一个输出元素,最终整个数据流被转换成一个新的DataStream。输出的数据流DataStream[OUT]类型可能和输入的数据流DataStream[IN]不同。

如业务需求可以对一些数据进行拼接字符,倍数扩大等场景使用。

我们可以重写MapFunctionRichMapFunction来自定义map函数:

我们新建一个map实现MapFunction接口并重写方法。我们实现的方法很简单就是将数据流中的元素拼接一段字符串。

将其作为参数传递到stream的map方法中。

但是运行时报错了

这块我也研究了半天/(ㄒoㄒ)/~~,此处需要注意的是,map()方法传入的参数需要严格指定泛型,来适应上下文环境,否则就会报错。因为我们做出修改。

运行后打印正常

filter

filter算子对每个元素进行过滤,过滤的过程使用一个filter函数进行逻辑判断。对于输入的每个元素,如果filter函数返回True,则保留,如果返回False,则丢弃。filter的输入和输出数据类型一致。

flatMap

对于map()来说,实现MapFunction也只是支持一对一的转换。
那么有时候你需要处理一个输入元素,但是要输出一个或者多个输出元素的时候,就可以用到flatMap()。

有一个输出时,完全可以当作map来用

flatMap支持一种特殊的数据类型Tuple

Tuple

Java API提供了Tuple1到Tuple25的类。Tuple的每个字段可以是任意的Flink支持的数据类型。关于Tuple中的数据访问,可以通过tuple.f4或者使用getter方法:tuple.getField(int position) 位置索引从0开始,比如一个Tuple2就可以理解为一个map但是相同的key不会重复,或者就是一个实体类。

 我们也可以在此基础上进行汇总求和

注意,虽然flatMap可以完全替代mapfilter,但Flink仍然保留了这三个API,主要因为mapfilter的语义更明确,更明确的语义有助于提高代码的可读性。map可以表示一对一的转换,代码阅读者能够确认对于一个输入,肯定能得到一个输出;filter则明确表示发生了过滤操作。

keyBy

DataStream  ->  KeyedStrem 逻辑的将一个流拆分成不相交的分区,每个分区包含具有相同key的元素,在内部以hash的方式实现的

滚动聚合算子

这些算子可以针对KeyedStrem的每一个直流做聚合

 sum()

 min()

 max()

 minBy()

 maxBy()

对于单一的基本类型的数据流,根本就无法进行分组操作。

所以我们创建一组简单的实体数据流进行keyBy操作。

keyBy参数类型有两种 int 和 string,而int类型的参数只适用于类型为tuple的数据,而我们的数据为pojo,所以需要传入string类型的字段。

还有一点值得注意的地方就是这两种方法的返回值的输出泛型是tuple类型

这是为什么呢?因为仔细观察keyBy的参数是(int...fields),说明可以传入多个参数。按多个key进行分组。多个key可能类型都不一样所以没法指定具体的分组后类型。所以就包装成了tuple类型返回。

max只是将实体中的max字段进行修改,其他字段并没有发生修改,优势会有歧义。

所以我们可以使用maxBy()

整个数据实体都发生了改变。

flink window

flink time

flink state

checkpoint

savepoint

### Flink 常见算子使用教程 #### Map 算子 `Map` 是一种基本转换操作,允许用户对输入流中的每一个元素应用一个函数来生成一个新的元素。此过程不会改变数据流的大小。 ```java DataStream<Integer> input = ...; DataStream<String> result = input.map(new MapFunction<Integer, String>() { @Override public String map(Integer value) throws Exception { return "Value is: " + value.toString(); } }); ``` 该代码片段展示了如何利用 `map()` 方法将整数类型的输入映射成字符串形式的结果[^3]。 #### Join 算子 `Join` 算子用于把两个不同的数据源基于某个共同字段组合在一起形成新的记录集合。这类似于SQL里的内联接(inner join),但也可以配置为其他类型的连接方式如左外连结(left outer join)等。 ```java DataStream<Tuple2<Long, String>> stream1 = ... DataStream<Tuple2<Long, Integer>> stream2 = ... stream1.join(stream2) .where(value -> value.f0).equalTo(value -> value.f0) .window(TumblingEventTimeWindows.of(Time.seconds(5))) .apply((left, right) -> new Tuple3<>(left.f0, left.f1, right.f1)) .print(); ``` 上述例子说明了怎样设置时间窗口并执行两路输入间的事件驱动型join操作[^4]。 #### Iterate 算子 对于那些需要反复处理直到满足特定终止条件的任务来说非常有用,比如某些图算法或是训练模型的过程。借助于iterate()可以轻松构建循环结构来进行多轮次的数据变换。 ```java IterationOperator<SomeType> iteration = env.createIterativeDataSet(inputData, "iterationName", maxIterations); // 定义每一轮迭代要做的工作... DataSet<SomeType> partialResult = iteration.flatMap(/* some logic */); partialResult.filter(/* condition to decide whether continue or not */) .outputTo(iteration.closeWith()); // 获取最终结果 DataSet<FinalOutputType> finalResults = /* combine all iterations' outputs */; finalResults.print(); ``` 这段伪代码描述了一个典型的迭代流程框架,其中包含了创建迭代环境、定义每次迭代的具体行为以及判断是否结束的标准[^1]。 #### Sink 算子 当完成所有的中间计算之后,通常还需要将得到的结果发送给外部存储系统或者其他服务端点。如果内置的支持不够,则可能需要开发人员自己编写定制化的sink组件以便对接目标平台。 ```java result.writeAsText("/path/to/output/file").setParallelism(1); // 将输出写入文件系统 ``` 这里给出了向本地磁盘保存文本格式化后的输出的一个简单案例[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值