DataStream的各类算子的介绍

读完Flink原理、实战与性能优化 这本书后,对各类算子的联合使用还不是很清楚。看到这篇文章写得比较清晰于是转载出来。
一、Map:对数据进行逐个遍历,常用作对数据集内数据的清洗和转换

input.print();    
SingleOutputStreamOperator<Tuple2<String, Integer>> map = input.map(new MapFunction<String, Tuple2<String, Integer>>() {
      @Override
      public Tuple2<String, Integer> map(String s) throws Exception {
          return new Tuple2<>(s, 1);
      }
 });
map.print();
对来的每一条数据,添加一个元素1,组成一个tuple二元组返回。

kafka输入:

代码输出:

二、FlatMap:输入一个元素,产生多个元素,将元素“炸开”

        input.print();
        SingleOutputStreamOperator<String> stringSingleOutputStreamOperator = input.flatMap(new FlatMapFunction<String, String>() {
            @Override
            public void flatMap(String s, Collector<String> collector) throws Exception {
                String[] strs = s.split(",");
                for (String str : strs) {
                    collector.collect(str);
                }
            }
        });
         stringSingleOutputStreamOperator.print();
kafka输入:

代码输出:

三、Filter:对输入的元素进行筛选过滤

        input.print();
        SingleOutputStreamOperator<String> hello = input.filter(new FilterFunction<String>() {
            @Override
            public boolean filter(String s) throws Exception {
                return !s.equals("hello");
            }
        });
        hello.print();
kafka输入:

程序输出:

四、KeyBy:输入DataStream,输出KeyedStream.将相同key值的数据放置在相同的分区中。

        input.print();
        SingleOutputStreamOperator<String> stringSingleOutputStreamOperator = input.flatMap(new FlatMapFunction<String, String>() {
            @Override
            public void flatMap(String s, Collector<String> collector) throws Exception {
                String[] strs = s.split(",");
                for (String str : strs) {
                    collector.collect(str);
                }
            }
        });
        SingleOutputStreamOperator<Tuple2<String, Integer>> map = stringSingleOutputStreamOperator.map(new MapFunction<String, Tuple2<String, Integer>>() {
            @Override
            public Tuple2<String, Integer> map(String s) throws Exception {
                return new Tuple2<>(s, 1);
            }
        });
 
        KeyedStream<Tuple2<String, Integer>, Tuple> tuple2TupleKeyedStream = map.keyBy(0);
        tuple2TupleKeyedStream.print();
kafka输入:

程序输出:

keyby(0)的意思就是拿第一个字段做聚合,所以,所有的第0个字段为a的元素都被分到一个分组中,由3号子任务输出,所有的第0个字段为b的元素都被1号子任务输出。

五、Reduce:输入KeyedStream,输出DataStream.将数据进行聚合处理,需要用户自定义ReduceFunction,且必要满足结合律和交换律。对上一步的KeyBy结果继续计算,代码如下:

        input.print();
        SingleOutputStreamOperator<String> stringSingleOutputStreamOperator = input.flatMap(new FlatMapFunction<String, String>() {
            @Override
            public void flatMap(String s, Collector<String> collector) throws Exception {
                String[] strs = s.split(",");
                for (String str : strs) {
                    collector.collect(str);
                }
            }
        });
        SingleOutputStreamOperator<Tuple2<String, Integer>> map = stringSingleOutputStreamOperator.map(new MapFunction<String, Tuple2<String, Integer>>() {
            @Override
            public Tuple2<String, Integer> map(String s) throws Exception {
                return new Tuple2<>(s, 1);
            }
        });
 
        KeyedStream<Tuple2<String, Integer>, Tuple> tuple2TupleKeyedStream = map.keyBy(0);
//        tuple2TupleKeyedStream.print();
        SingleOutputStreamOperator<Tuple2<String, Integer>> reduce = tuple2TupleKeyedStream.reduce(new ReduceFunction<Tuple2<String, Integer>>() {
            @Override
            public Tuple2<String, Integer> reduce(Tuple2<String, Integer> stringIntegerTuple2, Tuple2<String, Integer> t1) throws Exception {
                String key1 = stringIntegerTuple2.f0;
                int value1 = stringIntegerTuple2.f1;
                int value2 = t1.f1;
                return new Tuple2<String, Integer>(key1, value1 + value2);
            }
        });
        reduce.print();
kafka输入:

程序输出:

可以看到,key为a和b的元素,已经将value的值累加起来了。

六、Aggregations:输入KeyedStream,输出DataStream.其实是封装了一些聚合函数,sum、min、minBy、max、maxBy等等。我把输入元素转换为三元组,方便确定到具体元素。

1.sum:

        input.print();
        SingleOutputStreamOperator<Tuple3<String, Integer, Integer>> tuple3SingleOutputStreamOperator = input.flatMap(new FlatMapFunction<String, Tuple3<String, Integer, Integer>>() {
            @Override
            public void flatMap(String s, Collector<Tuple3<String, Integer, Integer>> collector) throws Exception {
                String[] strs = s.split(",");
                for (String str : strs) {
                    String[] kv = str.split(":");
                    collector.collect(new Tuple3<String, Integer, Integer>(kv[0], Integer.valueOf(kv[1]), (int) (Math.random() * 10)));
                }
            }
        });
//        tuple2SingleOutputStreamOperator.print();
        KeyedStream<Tuple3<String, Integer, Integer>, Tuple> tuple3TupleKeyedStream = tuple3SingleOutputStreamOperator.keyBy(0);
 
        tuple3TupleKeyedStream.sum(1).print("sum");
//        tuple3TupleKeyedStream.min(1).print("min");
//        tuple3TupleKeyedStream.max(1).print("max");
//        tuple3TupleKeyedStream.minBy(1).print("minBy");
//        tuple3TupleKeyedStream.maxBy(1).print("maxBy");
kafka输入:

因为我们可以确定到具体元素,所以我们可以跟一下代码,看看究竟会有什么输出。(我认为截图可以表达的更清楚)。

进入到KeyedStream.java的sum()方法。

进入到SumAggregator类里面,打断点继续跟。

显然,这个if判断为true。在该类的reduce()方法打断点跟。

value1是(a,1,5),value2是(a,2,6)。把value1拷贝,传参给fieldAccessor的set方法。fieldAccessor的实例化如下:

get方法如下:

所以get(value1)会返回1,get(value2)会返回2。adder会把两个值加起来。

刚刚说到把value1拷贝,传参给传参给fieldAccessor的set方法。所以,会把value1的第1个字段更新成add之后的值,然后返回。

所以,输出结果如下:

2.min和minBy:查阅官方资料,(Rolling aggregations on a keyed data stream. The difference between min and minBy is that min returns the minimum value, whereas minBy returns the element that has the minimum value in this field (same for max and maxBy).)。翻译(在KeyedStream上滚动聚合。min和minBy之间的区别是,min返回最小值,而minBy返回该字段中具有最小值的元素(max和maxBy也是如此)。)。拿(a,1)和(a,2)两个元素,按照官方说法,min会返回最小值1,minBy会返回最小值的元素(a,1,random),但是我的实验结果却不是这样。继续看源代码。这次不会从头跟断点了,只看关键的ComparableAggregator类中的reduce方法。

先来看min:

kafka输入:

value1是(a,1,6),value2是(a,2,3)

min不是byAggregate,所以进入else

c=1,说明value1小(要看comparator对象的实例化过程)。所以直接返回value1。返回了元素,而不是较小的值。这个和官网有出入,不知道是我操作有问题,还是我的版本有问题(我是1.7.0版本)。还请明白的大佬指教。

程序输出:

再看minBy:

kafka输入: 

这次if(byAggregate)判断为true,c=1,所以返回value1.

程序输出结果为:

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值