Flink之reduce操作

Flink的reduce操作是一种聚合操作,‌用于对数据进行分组或不分组的聚合计算,‌最终将数据聚合成一个元素。‌这个操作可以在分组的dataset上使用,‌也可以在不分组的dataset上使用。‌在分组的dataset上使用时,‌reduce操作应用用户定义的reduce函数将每个组减少为单个元素。‌对于每组输入元素,‌reduce函数连续地将元素对组合成一个元素,‌直到每个组只剩下一个元素。‌对于ReduceFunction,‌返回对象的key字段应与输入值匹配,‌这是因为reduce是可隐式组合的,‌并且从combine运算符发出的对象在传递给reduce运算符时再次按key分组。‌

具体来说,‌reduce操作适用于需要对数据进行聚合的场景,‌比如统计、‌计数等。‌例如,‌在日志分析中,‌可以使用reduce操作统计某个字段(‌如IP地址)‌的出现次数,‌或者统计某个单词在文本中出现的次数等。‌这种操作不仅限于分组数据,‌也可以直接应用于整个数据集,‌实现对整个数据集的聚合计算。‌

上图展示了reduce算子的原理:reduce在按照同一个Key分组的数据流上生效,它接受两个输入,生成一个输出,即两两合一地进行汇总操作,生成一个同类型的新元素。

reduce需要针对分组或者一个window(窗口)来执行,也就是分别对应于keyBy、window/timeWindow 处理后的数据,根据ReduceFunction将元素与上一个reduce后的结果合并,产出合并之后的结果

与简单聚合类似,reduce()操作也会将 KeyedStream 转换为 DataStream。它不会改变流的 元素数据类型,所以输出类型和输入类型是一样的。

 调用 KeyedStream 的 reduce()方法时,需要传入一个参数,实现 ReduceFunction 接口

实例1:相邻元素求和,定义tupple2类型的元组,数据为

("flink",1 )("flink",2)("flink",3)

/**相邻元素求和,
 * flink.transform.map,flink.transform.reduce flink.transform.reduce 必须和keyby结合
 * 原始数据
 * 1
 * 2
 * 3
 * 组成元组
 * flink.transform.map ->"flink",1  "flink",2  组成Tuple2的2元组 ("flink",1 )("flink",2)("flink",3)
 * 通过keyby按照key “flink”分组,
 * 通过reduce求和,对tuple2的第二列元素求和
 *13> (flink,1)
 * 13> (flink,3)
 * 13> (flink,6)
 * 13> (flink,10)
 *
 */
public class Test {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        DataStreamSource<String> numbersString = env.socketTextStream("127.0.0.1",9999);

       DataStream<Tuple2<String,Integer>> ds  = numbersString.map(new MapFunction<String, Tuple2<String,Integer>>() {

           @Override
           public Tuple2<String, Integer> map(String s) throws Exception {
               return new Tuple2<>("flink",Integer.parseInt(s));
           }
       }).keyBy(new KeySelector<Tuple2<String, Integer>, String>() {
            @Override
            public String getKey(Tuple2<String, Integer> stringIntegerTuple2) throws Exception {
                return stringIntegerTuple2.f0;
            }
        }).reduce(new ReduceFunction<Tuple2<String, Integer>>() {
            @Override
            public Tuple2<String, Integer> reduce(Tuple2<String, Integer> stringIntegerTuple2, Tuple2<String, Integer> t1) throws Exception {
                return new Tuple2<>(stringIntegerTuple2.f0,stringIntegerTuple2.f1+t1.f1);
            }
        });
        ds.print();
        env.execute("Flink Filter Example");
    }
}

实例2,逗号前边的为订单id,求订单和

package flink.transform.reduce;

import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.common.functions.ReduceFunction;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;

/**相邻元素求和,
1001,10
 1002,20
 1003,30
 1002,30
 1004,50
 1001,90          对同一比金额的订单进行累加运算
 先用map进行转换成tuple,再用keyBy进行分组,最后reduce 累加
 */
public class Test2 {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        DataStreamSource<String> numbersString = env.socketTextStream("127.0.0.1",9999);

      DataStream<Tuple2<String,Integer>>  td =  numbersString.map(new MapFunction<String,  Tuple2<String,Integer>>() {
            @Override
            public Tuple2<String, Integer> map(String s) throws Exception {
                return new  Tuple2<String,Integer>(s.split(",")[0],Integer.parseInt(s.split(",")[1]));
            }
        }).keyBy(0).reduce(new ReduceFunction<Tuple2<String, Integer>>() {
            @Override
            public Tuple2<String, Integer> reduce(Tuple2<String, Integer> stringIntegerTuple2, Tuple2<String, Integer> t1) throws Exception {
                return new Tuple2<>(stringIntegerTuple2.f0,stringIntegerTuple2.f1+t1.f1);
            }
        });
        td.print();
        env.execute();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薛定谔的猫1981

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值