Flink--Transform(键控流转换算子)

键控流转换算子

keyby

若现做聚合操作,必须先分组,所以keyby很重要
keyby算子比较特殊,并不是一步具体的执行操作
不是真正意义上的 aoprete
它就是定义了一下两个任务之间
数据的传输模式
keyby 基于定义的key做分组
基于每个key的hashcode 进行一个重分区

当同一个key进行重分区的时候必然会放入带同一个分区。当前分区一定有这个key的所有数据。同一个分区可以有多种key
keyby的转换涉及到一个数据结构的转换
datastream ==> keyedStream
观察数据源码:
datastream 本身没有聚合的方法 当转换为keyedStream 之后就有了聚合方法

这个 keyedStream 本质上还是继承自 datastream
keyby本身不是目的,目的是为了聚合

聚合算子

滚动聚合算子:在做聚合的过程中,数据时远远不断的 聚合的结果在之前的结果不断的更新。
常见的算子
sum
min
max
minby
maxby
min 和 minbu 的区别 要指定一个字段。
minby 输出的指定字段的最小值对应的 整个源数据
min 只是选取指定字段的最小值,别的字段输出第一条数据的值

min-minBy代码示例

创建环境读取数据

val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
val SensorData: DataStream[String] = env.readTextFile("F:\\idea1\\flinktest\\src\\main\\resources\\sensorfile.txt")

将读取的数据转换为样例类

val mapedData: DataStream[SensorReading] = SensorData.map(data => {
      val arr = data.split(", ")
      SensorReading(arr(0), arr(1).toLong, arr(2).toDouble)
    })

分组并进行min聚合

val resultData: DataStream[SensorReading] = mapedData.keyBy("id").min("temperature")

分组并进行minBy聚合

val resultData: DataStream[SensorReading] = mapedData.keyBy("id").minBy("temperature")

打印执行

resultData.print()
env.execute("aaaatest")

结果

min =>
3> SensorReading(“Sensor_1”,1547718145,59.0)
3> SensorReading(“Sensor_1”,1547718145,59.0)
3> SensorReading(“Sensor_1”,1547718145,36.0)
3> SensorReading(“Sensor_1”,1547718145,6.0)
3> SensorReading(“Sensor_1”,1547718145,3.0)
结果中只有min所处的字段发生了变化,而其他字段是第一条字段一致

minBy =>
3> SensorReading(“Sensor_1”,1547718129,136.0)
3> SensorReading(“Sensor_1”,1547718144,6.0)
3> SensorReading(“Sensor_1”,1547718152,3.0)
3> SensorReading(“Sensor_1”,1547718152,3.0)
3> SensorReading(“Sensor_1”,1547718152,3.0)
minBy的结果数据为最小值所对应的数据

说明一下:因为是并行处理,考虑到传输和计算,所以结果输出的顺序和文件中的顺序大不相同,若想处理顺序和文件顺序一致,可以把全局并行度设置为1

完整代码

//先创建环境
    val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
    val SensorData: DataStream[String] = env.readTextFile("F:\\idea1\\flinktest\\src\\main\\resources\\sensorfile.txt")
    // 转换为样例类
    val mapedData: DataStream[SensorReading] = SensorData.map(data => {
      val arr = data.split(", ")
      SensorReading(arr(0), arr(1).toLong, arr(2).toDouble)
    })


    val resultData: DataStream[SensorReading] = mapedData.keyBy("id").min("temperature")

    val resultData2: DataStream[SensorReading] = mapedData.keyBy("id").minBy("temperature")
    resultData.print()
    resultData2.print()
    env.execute("aaaatest")

reduce代码示例

需求:输出结果包含最新的时间戳和最小的温度值

创建环境读取数据

val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
val SensorData: DataStream[String] = env.readTextFile("F:\\idea1\\flinktest\\src\\main\\resources\\sensorfile.txt")

将读取的数据转换为样例类

val mapedData: DataStream[SensorReading] = SensorData.map(data => {
      val arr = data.split(", ")
      SensorReading(arr(0), arr(1).toLong, arr(2).toDouble)
    })

reduce1:使用lamda表达式

 val resultData: DataStream[SensorReading] = mapedData.keyBy("id").reduce { (curdata, newdata) =>
      SensorReading(curdata.id, newdata.timeStamp.max(curdata.timeStamp), curdata.temperature.min(newdata.temperature))
    }

reduce2:自定义类实现reduceFunction

val resultData: DataStream[SensorReading] = mapedData.keyBy("id").reduce(new myReduce)

// 自己实现一个function 首先继承reducefunction[处理的数据]
class myReduce extends ReduceFunction[SensorReading] {
  override def reduce(curdata: SensorReading, newdata: SensorReading): SensorReading = {
    SensorReading(curdata.id, newdata.timeStamp.max(curdata.timeStamp), curdata.temperature.min(newdata.temperature))
  }
}
// reduce就是把数据进行规约,输入参数1表示是之前规约的结果,输入参数2表新数据,然后返回一个规约之后的结果
// 这种方式的核心内容和表达式方式是一样的

打印执行

    resultData.print()
    env.execute("aaaa")

完整代码

object transformtest {
  def main(args: Array[String]): Unit = {


    //先创建环境
    val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
    val SensorData: DataStream[String] = env.readTextFile("F:\\idea1\\flinktest\\src\\main\\resources\\sensorfile.txt")
    // 转换为样例类
    val mapedData: DataStream[SensorReading] = SensorData.map(data => {
      val arr = data.split(", ")
      SensorReading(arr(0), arr(1).toLong, arr(2).toDouble)
    })

    val resultData: DataStream[SensorReading] = mapedData.keyBy("id").reduce { (curdata, newdata) =>
      SensorReading(curdata.id, newdata.timeStamp.max(curdata.timeStamp), curdata.temperature.min(newdata.temperature))
    }

    val resultData2: DataStream[SensorReading] = mapedData.keyBy("id").reduce(new myReduce)
    resultData.print()
    resultData2.print()
    env.execute("aaaa")
  }
}

class myReduce extends ReduceFunction[SensorReading] {
  override def reduce(curdata: SensorReading, newdata: SensorReading): SensorReading = {
    SensorReading(curdata.id, newdata.timeStamp.max(curdata.timeStamp), curdata.temperature.min(newdata.temperature))
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值