• FlinkTransform(转换)


    书接上回。

    3.Transform 转换算子【代码示例统一放在最后边】

    3.1 map

     
    val streamMap = stream.map { x => x * 2 }
     

    3.2 flatMap

    flatMap 的函数签名:def flatMap[A,B](as: List[A])(f: A ⇒ List[B]): List[B]
    例如: flatMap(List(1,2,3))(i ⇒ List(i,i))
    结果是 List(1,1,2,2,3,3),
    而 List("a b", "c d").flatMap(line ⇒ line.split(" "))
    结果是 List(a, b, c, d)。
    val streamFlatMap = stream.flatMap{
        x => x.split(" ")
    }
     

    3.3 Filter

    val streamFilter = stream.filter{
        x => x == 1
    }
     

    3.4 KeyBy

    DataStream → KeyedStream:逻辑地将一个流拆分成不相交的分区,每个分区包含具有相同 key 的元素,在内部以 hash 的形式实现的。
     

    3.5 滚动聚合算子(Rolling Aggregation)

    这些算子可以针对 KeyedStream 的每一个支流做聚合。
    • sum()
    • min()
    • max()
    • minBy()
    • maxBy()

    3.6 Reduce

    KeyedStream → DataStream:一个分组数据流的聚合操作,合并当前的元素和上次聚合的结果,产生一个新的值,返回的流中包含每一次聚合的结果,而不是只返回最后一次聚合的最终结果。
     

    3.7 Split和Select【注:1.13版本已竟没有该函数,推荐使用侧输出】

    Split:
    DataStream → SplitStream:根据某些特征把一个 DataStream 拆分成两个或者多个 DataStream。
     
     
    Select:
     
    SplitStream→DataStream:从一个 SplitStream 中获取一个或者多个DataStream。
     
    针对同一条流多次独立调用.filter()方法进行筛选,就可以得到拆分之后的流,它将原始数据流 stream 复制三份,然后对每一份分别做筛选;这明显是不够高效。
    早期的版本中,DataStream API 中提供了一个.split()方法,基本思路是按照筛选条件,给数据分类“盖戳”;然后基于这条盖戳之后的流,分别拣选想要的“戳”就可以得到拆分后的流。因为只是“盖戳”拣选,所以无法对数据进行转换,分流后的数据类型必须跟原始流保持一致。这就极大地限制了分流操作的应用场景。
    推荐使用使用侧输出流。
    Flink的Side Output侧输出流的作用在于将主数据分割成多个不同的侧输出流。侧输出结果流的数据类型不需要与主数据流的类型一致,不同侧输出流的类型也可以不同。
    在使用侧输出的时候需要先定义一个OutputTag,来标识 Side Output,代表这个 Tag 是要收集哪种类型的数据。
     
     

    3.8 Connect和CoMap

     
    DataStream,DataStream → ConnectedStreams:连接两个保持他们类型的数据流,两个数据流被 Connect 之后,只是被放在了一个同一个流中,内部依然保持各自的数据和形式不发生任何变化,两个流相互独立。
     
    coMap,CoFlatMap
     
    ConnectedStreams → DataStream:作用于 ConnectedStreams 上,功能与 map和 flatMap 一样,对 ConnectedStreams 中的每一个 Stream 分别进行 map 和 flatMap处理。
     

    3.9 Union

     
    DataStream → DataStream:对两个或者两个以上的 DataStream 进行 union 操作,产生一个包含所有 DataStream 元素的新 DataStream。
     
    Connect与Union区别
    1.Union 之前两个流的类型必须是一样,Connect 可以不一样,在之后的 coMap中再去调整成为一样的。
    2.Connect 只能操作两个流,Union 可以操作多个。
     

    代码:

    package com.zhen.flink.api
    
    import org.apache.flink.api.common.functions.ReduceFunction
    import org.apache.flink.streaming.api.functions.ProcessFunction
    import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment
    import org.apache.flink.streaming.api.scala._
    import org.apache.flink.util.Collector
    
    /**
      * @Author FengZhen
      * @Date 6/7/22 4:25 PM
      * @Description TODO
      */
    object TransformTest {
    
      lazy val HIGH_TEMP: OutputTag[SensorReading] = new OutputTag[SensorReading]("高温数据")
      lazy val LOW_TEMP: OutputTag[SensorReading] = new OutputTag[SensorReading]("低温数据")
    
      def main(args: Array[String]): Unit = {
        val env = StreamExecutionEnvironment.getExecutionEnvironment
    
        env.setParallelism(1)
    
        // 0.读取数据
        val filePath = "/Users/FengZhen/Desktop/accumulate/0_project/flink_learn/src/main/resources/data/sensor.txt"
        val inputStream = env.readTextFile(filePath)
    
        // 1.先转换成样例数据
        val dataStream: DataStream[SensorReading] = inputStream
          .map(
            data => {
              val arr = data.split(",")
              SensorReading(arr(0), arr(1).toLong, arr(2).toDouble)
            }
          )
    
        // 2.分组聚合, 输出每个传感器当前最小值
        val aggStream = dataStream
            .keyBy("id")  //根据ID进行分组
            //.min("temperature")   //输出中只temperature字段有变化,其它字段无变化
            .minBy("temperature") //使用minBy可以解决上述其它字段不变的问题
    
    //    aggStream.print()
    
        // 3.需要输出当前最小的温度值,以及最近的时间戳,要用reduce
        val resultStream = dataStream
            .keyBy("id")  //根据ID进行分组
    //        .reduce(
    //          (curState, newData) => {
    //            //假定数据是按timestamp增续进来的
    //            SensorReading(
    //              curState.id,
    //              newData.timestamp,
    //              curState.temperature.min(newData.temperature)
    //            )
    //          }
    //        )
            .reduce(new MyReduceFunction)
    
    //    resultStream.print()
    
    
        // 4.多流转换操作
        // 4.1 分流,将传感器温度数据分成低温、高温两条流
        val processStream = dataStream.process(new MySplitProcessFunction)
    
        val highStream = processStream.getSideOutput(HIGH_TEMP)
        val lowStream = processStream.getSideOutput(LOW_TEMP)
    
        highStream.print("high:")
        lowStream.print("low:")
    
        // 4.2 合流,connect
        val warningStream = highStream.map(
          data => (data.id, data.temperature)
        )
        val connectedStreams = warningStream.connect(lowStream)
    
        // 用coMap对数据进行分别处理
        val coMapResultStream = connectedStreams
            .map(
              warningData => (warningData._1, warningData._2, "warning"),
              lowTempData => (lowTempData.id, "healthy")
            )
    
        coMapResultStream.print("coMap:")
    
        //4.3 Union合流
        val unionStream = highStream.union(lowStream)
        unionStream.print("union")
    
        env.execute("transform test")
    
      }
    
      class MyReduceFunction extends ReduceFunction[SensorReading] {
        override def reduce(value1: SensorReading, value2: SensorReading): SensorReading = {
          SensorReading(
            value1.id,
            value2.timestamp,
            value1.temperature.min(value2.temperature)
          )
        }
      }
    
      class MySplitProcessFunction extends ProcessFunction[SensorReading, SensorReading] {
    
        override def processElement(value: SensorReading, ctx: ProcessFunction[SensorReading, SensorReading]#Context, out: Collector[SensorReading]): Unit = {
    
          if(value.temperature > 30){
            ctx.output(HIGH_TEMP, value)
          }else if(value.temperature <= 30){
            ctx.output(LOW_TEMP, value)
          }else{
            out.collect(value)
          }
    
        }
      }
    
    }
  • 相关阅读:
    dapper 批量删除、新增、修改说明
    android 加载assets目录下的静态html文件案例
    webstorm中使用git提交代码时出现unversioned files错误
    windows server 2008 R2 x64 部署.net core 3.1项目
    asp.net core 项目添加nlog日志(loggerFactor.AddNLog 过时处理(.net core 3.1))
    机器学习笔记之一步步教你轻松学主成分分析PCA降维算法
    机器学习笔记之类别特征处理
    机器学习笔记之range, numpy.arange 和 numpy.linspace的区别
    机器学习笔记之Numpy的random函数
    机器学习笔记之矩阵分解 SVD奇异值分解
  • 原文地址:https://www.cnblogs.com/EnzoDin/p/16357419.html
Copyright © 2020-2023  润新知