Flink 系例 之 Apply

Apply算子:对窗口内的数据流进行处理

示例环境

java.version: 1.8.x
flink.version: 1.11.1

示例数据源 (项目码云下载)

Flink 系例 之 搭建开发环境与数据

Apply.java

import com.flink.examples.DataSource;
import org.apache.flink.api.java.functions.KeySelector;
import org.apache.flink.api.java.tuple.Tuple3;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.windowing.WindowFunction;
import org.apache.flink.streaming.api.windowing.windows.GlobalWindow;
import org.apache.flink.util.Collector;

import java.util.Iterator;
import java.util.List;

/**
 * @Description Apply方法:对窗口内的数据流进行处理
 */
public class Apply {

    /**
     * 遍历集合,分别打印不同性别的总人数与年龄之和
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        List<Tuple3<String, String, Integer>> tuple3List = DataSource.getTuple3ToList();
        DataStream<String> dataStream = env.fromCollection(tuple3List)
                .keyBy((KeySelector<Tuple3<String, String, Integer>, String>) k -> k.f1)
                //按数量窗口滚动,每3个输入窗口数据流,计算一次
                .countWindow(3)
                //只能基于Windowed窗口Stream进行调用
                .apply(
                        //WindowFunction<IN, OUT, KEY, W extends Window>
                        new WindowFunction<Tuple3<String, String, Integer>, String, String, GlobalWindow>() {
                            /**
                             * 处理窗口数据集合
                             * @param s         从keyBy里返回的key值
                             * @param window    窗口类型
                             * @param input     从窗口获取的所有分区数据流
                             * @param out       输出数据流对象
                             * @throws Exception
                             */
                            @Override
                            public void apply(String s, GlobalWindow window, Iterable<Tuple3<String, String, Integer>> input, Collector<String> out) throws Exception {
                                Iterator<Tuple3<String, String, Integer>> iterator = input.iterator();
                                int total = 0;
                                int i = 0;
                                while (iterator.hasNext()){
                                    Tuple3<String, String, Integer> tuple3 = iterator.next();
                                    total += tuple3.f2;
                                    i ++ ;
                                }
                                out.collect(s + "共:"+i+"人,累加总年龄:" + total);
                            }
                        });
        dataStream.print();
        env.execute("flink Filter job");
    }
}

打印结果

4> girl共:3人,累加总年龄:74
2> man共:3人,累加总年龄:79
### Flink 数据转换操作及实现方式 #### 1. 基本数据转换操作 Flink 提供了一列用于数据流的操作符来执行各种转换逻辑。常见的基本转换操作包括 `map`、`flatMap` 和 `filter`。 - **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(); } }); ``` - **FlatMap**: 类似于 `map`,但是可以生成零个或多个输出元素。 ```java DataStream<String> lines = ...; DataStream<String> words = lines.flatMap(new FlatMapFunction<String, String>() { @Override public void flatMap(String line, Collector<String> out) throws Exception { for (String word : line.split("\\s+")) { out.collect(word); } } }); ``` - **Filter**: 过滤掉不符合条件的数据项。 ```java DataStream<Integer> numbers = ...; DataStream<Integer> filteredNumbers = numbers.filter(new FilterFunction<Integer>() { @Override public boolean filter(Integer value) throws Exception { return value % 2 == 0; // 只保留偶数 } }); ``` 上述三种基础变换能够满足大部分简单的业务需求[^1]。 #### 2. 聚合类转换操作 对于需要累积计算的任务,比如求和(`sum`)、最小值(`min`)等,则可以通过特定的聚合算子完成。需要注意的是,在流环境中,由于数据持续到达,因此这类运算通常作用于窗口内的有限集合之上[^3]。 - **Sum** 对某个字段的所有记录做累加汇总: ```java DataStream<Tuple2<String, Integer>> clicksPerUrl = ... DataStream<Tuple2<String, Integer>> sumClicks = clicksPerUrl.keyBy(value -> value.f0).sum(1); ``` - **Min/Max** 计算每组中的最小值或最大值: ```java DataStream<Tuple2<String, Long>> minTimestamps = events.keyBy(event -> event.f0).min(1); ``` 这里的关键在于理解如何定义分组依据以及选择合适的字段来进行比较[^4]。 #### 3. 复杂事件处理与连接 当涉及到多条独立但相互关联的消息时,可能需要用到更复杂的模式匹配或是与其他数据源联合查询的能力。这方面的典型代表就是 Join 操作及其变种形式 CoGroup 和 GroupBy 等。 - **Join** 实现两个不同源头之间基于共同属性的信息拼接: ```java DataStream<OrderEvent> orders = ...; DataStream<ShipmentEvent> shipments = ...; SingleOutputStreamOperator<JoinedOrderAndShipment> joinedEvents = orders.join(shipments) .where(order -> order.orderId()) .equalTo(shipment -> shipment.orderId()) .window(TumblingEventTimeWindows.of(Time.seconds(5))) .apply((order, shipment) -> new JoinedOrderAndShipment(order, shipment)); ``` 此部分强调了在实际应用中合理设计键的选择策略的重要性,从而确保性能最优的同时达到预期效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值