【FLink-3-Flink算子-Transformation算子】

Transformation算子

1.Map算子

在这里插入图片描述

2.FlatMap算子

在这里插入图片描述

3.Project算子

4.Filter算子

在这里插入图片描述

5.分组算子

在这里插入图片描述

6.滚动聚合算子(只能在KeyedStream流上调用)

  • sum算子

  • min算子

    • min算子 只更新对应字段的值,而其他字段的值保留之前的一次状态的值,这样的话,就会导致数据的准确性问题。
  • minBy算子

    • minBy算子,更新整个字段的值,可以获取到所有字段的值,能保证数据的准确性。
  • max算子

  • maxBy算子
    在这里插入图片描述

注意:
1. max/maxBy 都是滚动聚合,算子不会把收到的所有数据全部攒起来,而是只在状态中记录上一次的聚合值,然后当新数据到达时,会根据逻辑去更新 状态中记录的聚合值,并输出最新状态数据。
2. max / maxBy 区别:更新状态的逻辑,max只更新最大值的字段;而maxBy会更新整条数据。

  • reduce算子
    reduce底层逻辑也是一个滚动聚合的逻辑。
    在这里插入图片描述
    reduce实现Sum的效果:
    在这里插入图片描述

代码示例:

import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.common.functions.ReduceFunction;
import org.apache.flink.api.common.typeinfo.TypeHint;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.api.java.tuple.Tuple4;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.KeyedStream;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.util.Collector;

import java.io.Serializable;
import java.util.List;


public class FlinkTransformationDemos {

    public static void main(String[] args) throws Exception {

        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);

        // {"uid":1,"name":"zs","friends":[{"fid":2,"name":"aa"},{"fid":3,"name":"bb"}]}
        /*DataStreamSource<String> streamSource = env.fromElements(
                "{\"uid\":1,\"name\":\"zs\",\"friends\":[{\"fid\":2,\"name\":\"aa\"},{\"fid\":3,\"name\":\"bb\"}]}",
                "{\"uid\":2,\"name\":\"ls\",\"friends\":[{\"fid\":1,\"name\":\"cc\"},{\"fid\":2,\"name\":\"aa\"}]}",
                "{\"uid\":3,\"name\":\"ww\",\"friends\":[{\"fid\":2,\"name\":\"aa\"}]}",
                "{\"uid\":4,\"name\":\"zl\",\"friends\":[{\"fid\":3,\"name\":\"bb\"}]}",
                "{\"uid\":5,\"name\":\"tq\",\"friends\":[{\"fid\":2,\"name\":\"aa\"},{\"fid\":3,\"name\":\"bb\"}]}"
        );*/


        DataStreamSource<String> streamSource = env.readTextFile("E:\\2020code\\gmall2021-parent\\flink-2023-demo-doit\\src\\main");


        /**
         * map算子的演示
         */
        // 把每条json数据,转成javabean数据
        SingleOutputStreamOperator<UserInfo> beanStream = streamSource.map(json -> JSON.parseObject(json, UserInfo.class));
        /*beanStream.print();*/


        /**
         * filter算子的演示
         *   请过滤掉好友超过3位的用户数据
         */
        SingleOutputStreamOperator<UserInfo> filtered = beanStream.filter(bean -> bean.getFriends().size() <= 3);
        /*filtered.print();*/


        /**
         * flatmap算子的演示
         *  把每个用户的好友信息,全部提取出来(带上用户自身的信息),并且压平,放入结果流中
         *  {"uid":1,"name":"zs","gender":"male","friends":[{"fid":2,"name":"aa"},{"fid":3,"name":"bb"}]}
         *  =>
         *  {"uid":1,"name":"zs","gender":"male","fid":2,"fname":"aa"}
         *  {"uid":1,"name":"zs","gender":"male","fid":3,"fname":"bb"}
         */
        SingleOutputStreamOperator<UserFriendInfo> flatten = filtered.flatMap(new FlatMapFunction<UserInfo, UserFriendInfo>() {
            @Override
            public void flatMap(UserInfo value, Collector<UserFriendInfo> out) throws Exception {
                // 把friends列表提取出来,一个一个地返回
                List<FriendInfo> friends = value.getFriends();
                /* friends.forEach(x->out.collect(new UserFriendInfo(value.getUid(), value.getName(), value.getGender(),x.getFid(),x.getName() )));*/
                for (FriendInfo x : friends) {
                    out.collect(new UserFriendInfo(value.getUid(), value.getName(), value.getGender(), x.getFid(), x.getName()));
                }
            }
        });
        /* flatten.print();*/


        /**
         * keyBy算子的演示
         * 对上一步的结果,按用户性别分组
         *
         * 滚动聚合算子(只能在 KeyedStream 流上调用):  sum算子 、 min算子 、 minBy算子 、 max算子、  maxBy算子、 reduce算子的演示
         * 并统计:
         *    各性别用户的好友总数
         *
         *    各性别中,用户好友数量最大值
         *    各性别中,用户好友数量最小值
         *
         *    求各性别中,好友数量最大的那个人
         *    求各性别中,好友数量最小的那个人
         *
         */
        // 各性别用户的好友总数
        KeyedStream<Tuple2<String, Integer>, String> keyedStream = flatten.map(bean -> Tuple2.of(bean.getGender(), 1)).returns(new TypeHint<Tuple2<String, Integer>>() {
        })
                .keyBy(tp -> tp.f0);

        keyedStream
                .sum(1);
        /*genderFriendCount.print();*/

        // 各性别中,用户好友数量最大值

        /**
         * max / maxBy  都是滚动聚合:  算子不会把收到的所有数据全部攒起来;而是只在状态中记录上一次的聚合值,然后当新数据到达的时候,会根据逻辑去更新 状态中记录的聚合值,并输出最新状态数据
         * max / maxBy  区别: 更新状态的逻辑!  max只更新要求最大值的字段;  而 maxBy 会更新整条数据;
         * 同理,min和minBy也如此
         */
        SingleOutputStreamOperator<Tuple4<Integer, String, String, Integer>> tuple4Stream = beanStream.map(bean -> Tuple4.of(bean.getUid(), bean.getName(), bean.getGender(), bean.getFriends().size())).returns(new TypeHint<Tuple4<Integer, String, String, Integer>>() {
        });


        tuple4Stream
                .keyBy(tp -> tp.f2)
                /*.max(3); */              // 各性别中,用户好友数量最大值
                .maxBy(3);  // 求各性别中,好友数量最大的那个人

        /*genderUserFriendsMaxCount.print();*/


        /**
         * reduce 算子 使用演示
         * 需求: 求各性别中,好友数量最大的那个人,而且如果前后两个人的好友数量相同,则输出的结果中,也需要将uid/name等信息更新成后面一条数据的值
         *
         */
        SingleOutputStreamOperator<Tuple4<Integer, String, String, Integer>> reduceResult = tuple4Stream.keyBy(tp -> tp.f2)
                .reduce(new ReduceFunction<Tuple4<Integer, String, String, Integer>>() {
                    /**
                     *
                     * @param value1  是此前的聚合结果
                     * @param value2  是本次的新数据
                     * @return 更新后的聚合结果
                     * @throws Exception
                     */
                    @Override
                    public Tuple4<Integer, String, String, Integer> reduce(Tuple4<Integer, String, String, Integer> value1, Tuple4<Integer, String, String, Integer> value2) throws Exception {

                        if (value1 == null || value2.f3 >= value1.f3) {
                            return value2;
                        } else {
                            return value1;
                        }
                    }
                });
        /*reduceResult.print();*/


        /**
         * 用reduce,来实现sum算子的功能
         * 求:  对上面的  4元组数据  1,ua,male,2  ,求各性别的好友数总和
         * TODO
         */
        SingleOutputStreamOperator<Tuple4<Integer, String, String, Integer>> reduceSum = tuple4Stream.keyBy(tp -> tp.f2)
                .reduce(new ReduceFunction<Tuple4<Integer, String, String, Integer>>() {
                    @Override
                    public Tuple4<Integer, String, String, Integer> reduce(Tuple4<Integer, String, String, Integer> value1, Tuple4<Integer, String, String, Integer> value2) throws Exception {
                        value2.setField(value2.f3 + (value1 == null ? 0 : value1.f3), 3);
                        return value2;
                    }
                });
        reduceSum.print();


        env.execute();

    }
}

@Data
class UserInfo implements Serializable {
    private int uid;
    private String name;
    private String gender;
    private List<FriendInfo> friends;
}

@Data
class FriendInfo implements Serializable {
    private int fid;
    private String name;
}

@Data
@AllArgsConstructor
class UserFriendInfo implements Serializable {
    private int uid;
    private String name;
    private String gender;
    private int fid;
    private String fname;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值