Flink学习笔记(七):flink聚合函数

Flink的AggregateFunction是一个基于中间计算结果状态进行增量计算的函数,可以用在多种场景的实时计算中,而且采用迭代方式,运行效率比较高。

一、接口

我们查看AggregateFunction接口可以看到它有三个参数

输入类型(IN)

累加器类型(ACC)

输出类型(OUT)

@PublicEvolving
public interface AggregateFunction<IN, ACC, OUT> extends Function, Serializable {
    //创建一个新的累加器,启动一个新的聚合,负责迭代状态的初始化
    ACC createAccumulator(); 
    //对于数据的每条数据,和迭代数据的聚合的具体实现
    ACC add(IN var1, ACC var2);
    //从累加器获取聚合的结果
    OUT getResult(ACC var1);
    //合并两个累加器,返回一个具有合并状态的累加器(sessionwindow可用)
    ACC merge(ACC var1, ACC var2);
}

那么我们什么时候可以使用AggregateFunction呢?

二、场景

问题:有一天小白想统计一下每5次各科成绩总和以及平均值,有了很多数据,你能帮助小白设计下如何方便的统计么?

统计的科目有:“语文”, “数学”, “英语”, “物理”, "化学"

我们先定义一个科目的数组SUBJECT

private static final String[] SUBJECT = { "语文", "数学", "英语", "物理", "化学" };

然后通过数据流获取相关数据(本例随机生成成绩)

数据源结构为Tuple3<String, String, Integer>
分别表示 姓名,科目,成绩

// 获取执行环境
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
env.setParallelism(1);

DataStream<Tuple3<String, String, Integer>> source = env.addSource(new SourceFunction<Tuple3<String, String, Integer>>() {
    private volatile boolean isRunning = true;
    private final Random random = new Random();
    @Override
    public void run(SourceContext<Tuple3<String, String, Integer>> ctx) throws Exception {
        while (isRunning) {
            TimeUnit.SECONDS.sleep(1);
            ctx.collect(Tuple3.of("小白", SUBJECT[random.nextInt(SUBJECT.length)], (int)(Math.random() * 50) + 50));
        }
    }
    @Override
    public void cancel() {
        isRunning = false;
    }
});

获取数据流之后,执行数据的聚合,数据格式为Tuple4<String, String, Integer, Double>
分别表示 姓名,科目,成绩,平均成绩

DataStream<Tuple4<String, String, Integer, Double>> score = source
        .keyBy(1)
        .countWindow(5)
        .aggregate(new AverageAggrate());

score.print();

那么 AverageAggrate()的方法如何实现呢?

三、实现

首先我们建立AverageAggrate 继承接口AggregateFunction,接口的类型如下

输入类型(IN)
Tuple3<String, String, Integer> 表示 姓名,科目,分数

累加器类型(ACC)
Tuple4<String, String, Integer, Integer> 表示 姓名,科目,总分数,统计次数

输出类型(OUT)
Tuple4<String, String, Integer, Double> 表示 姓名,科目,总分数,每个统计

public static class AverageAggrate implements AggregateFunction<Tuple3<String, String, Integer>, Tuple4<String, String, Integer, Integer>, Tuple4<String, String, Integer, Double>> {
    @Override
    public Tuple4<String, String, Integer, Integer> createAccumulator() {
        return new Tuple4<>("", "", 0, 0);
    }

    @Override
    public Tuple4<String, String, Integer, Integer> add(Tuple3<String, String, Integer> value, Tuple4<String, String, Integer, Integer> acc) {
        return new Tuple4<>(value.f0, value.f1, acc.f2 + value.f2, acc.f3 + 1);
    }

    @Override
    public Tuple4<String, String, Integer, Double> getResult(Tuple4<String, String, Integer, Integer> acc) {
        return Tuple4.of(acc.f0, acc.f1, acc.f2, (double)acc.f2 / acc.f3);
    }

    @Override
    public Tuple4<String, String, Integer, Integer> merge(Tuple4<String, String, Integer, Integer> acc1, Tuple4<String, String, Integer, Integer> acc2) {
        return null;
    }
}

运行结果:
在这里插入图片描述
小白每个科目 每5次的平均结果和总分数就统计完成啦

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值