Flink de entrada a fragancia real (5, Flink varias operaciones de conversión de datos (transformación))

mapa:

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

mapa plano

Es decir, la colección anidada se convierte y aplana en una colección no anidada.
Por ejemplo: si una lista quiere dividir y extraer datos separados por espacios, puede hacer esto:
List ("ab", "cd"). FlatMap (line => line. El
resultado final de split ("")) es: List (a, b, c, d
val streamFlatMap = stream.flatMap {
x => x.split ("")
}

filtrar

Es similar a if para filtrar, dar una expresión lambda y devolver un valor de tipo bool. Según si el resultado final es verdadero, se juzga si el resultado actual se conserva
val streamFilter = stream.filter {
x => x == 1
}

KeyBy
Flink de entrada a fragancia real (5, Flink varias operaciones de conversión de datos (transformación))
primero se agrupa y luego se agrega.
DataStream -> KeyedStream: Divide lógicamente un flujo en particiones separadas. Cada partición contiene el mismo elemento clave y se implementa en forma de hash.

Operadores de agregación rodante (Agregación rodante)
Estos operadores pueden realizar agregaciones para cada afluente de KeyedStream.
suma ()
min ()
max ()
minBy ()
maxBy ()

Reducir

Dividir y seleccionar

División

DataStream -> SplitStream: De acuerdo con ciertas características, divida un DataStram en dos o más DataStream

Seleccione

Flink de entrada a fragancia real (5, Flink varias operaciones de conversión de datos (transformación))
SplitStream-> DataStream: obtenga uno o más DataStream de un SplitStream.

Requisitos: Los datos del sensor se dividen en dos flujos de acuerdo con la temperatura (30 grados como límite).

Conectar y CoMap

Los flujos se fusionan, pero solo los dos flujos se fusionan en uno solo. Los dos flujos fusionados son independientes y no se afectan entre sí.

Flink de entrada a fragancia real (5, Flink varias operaciones de conversión de datos (transformación))

DataStream, DataStream -> ConnectedStreams: conecta dos flujos de datos que mantienen sus tipos. Una vez que los dos flujos de datos están conectados, solo se colocan en el mismo flujo. Los datos internos y las formas de los dos flujos de datos permanecen sin cambios. Las corrientes son independientes entre sí.
CoMap, CoFlatMap

Flink de entrada a fragancia real (5, Flink varias operaciones de conversión de datos (transformación))

ConnectedStreams -> DataStream: Actuando en ConnectedStreams, la función es la misma que map y flatMap, cada Stream en ConnectedStreams se procesa con map y flatMap respectivamente.

Unión

La fusión de secuencias consiste en fusionar directamente los datos de dos secuencias en una sola. Los datos de las dos secuencias deben ser coherentes, de lo contrario, no se pueden utilizar.

Flink de entrada a fragancia real (5, Flink varias operaciones de conversión de datos (transformación))

alrededores:

Cree un nuevo paquete, com.mafei.apitest, cree una nueva clase de objeto scala, TransformTest

package com.mafei.apitest

import org.apache.flink.api.common.functions.ReduceFunction
import org.apache.flink.streaming.api.scala.{StreamExecutionEnvironment, createTypeInformation}

//获取传感器数据

case class SensorReadingTest(id: String,timestamp: Long, temperature: Double)

object TransformTest {
  def main(args: Array[String]): Unit = {
    //创建执行环境
    val env = StreamExecutionEnvironment.getExecutionEnvironment

    val inputStream= env.readTextFile("/opt/java2020_study/maven/flink1/src/main/resources/sensor.txt")
    env.setParallelism(1)

//    inputStream.print()
    //先转换成样例类类型
    val dataStream = inputStream
      .map(data =>{
        val arr = data.split(",")   //按照,分割数据,获取结果
        SensorReadingTest(arr(0), arr(1).toLong,arr(2).toDouble)  //生成一个传感器类的数据,参数中传toLong和toDouble是因为默认分割后是字符串类别
      })
    /**
     * dataStream.print()  输出样例
      1> SensorReadingTest(sensor4,1603766240,40.1)
      4> SensorReadingTest(sensor4,1603766284,44.0)
      2> SensorReadingTest(sensor1,1603766281,41.0)
      3> SensorReadingTest(sensor3,1603766283,43.0)
      2> SensorReadingTest(sensor2,1603766282,42.0)

     */

    //分组聚合,输出每个传感器当前最小值
    val aggStream = dataStream
      .keyBy("id")   //根据id来进行分组
//      .min("temperature")  //获取每一组中temperature 为最小的数据
      .min("temperature")  //获取每一组中temperature 为最小的数据

    /**
    aggStream.print()

      1> SensorReadingTest(sensor1,1603766281,41.0)
      2> SensorReadingTest(sensor3,1603766283,43.0)
      4> SensorReadingTest(sensor2,1603766282,42.0)
      1> SensorReadingTest(sensor4,1603766240,40.1)   // 所有sensor的数据只会输出最小的值
      1> SensorReadingTest(sensor4,1603766240,40.1)   // 所有sensor的数据只会输出最小的值
     */

    //需要输出当前最小的温度值,以及最近的时间戳,要用到reduce
    val resultStream = dataStream
      .keyBy("id")
//      .reduce((curState, newData)=>{
//        SensorReadingTest(curState.id,newData.timestamp, curState.temperature.min(newData.timestamp))
//      })
      .reduce( new MyreduceFunction)   //如果不用上面的lambda表达式,也可以自己写实现类,一样的效果,二选一

    /**

    print(resultStream.print())
    SensorReadingTest(sensor2,1603766282,42.0)
    SensorReadingTest(sensor3,1603766283,43.0)
    SensorReadingTest(sensor4,1603766240,40.1)
    SensorReadingTest(sensor4,1603766284,40.1)  //可以看到虽然sensor4的时间戳还是在更新,但是temperature 一直是最小的一个
    SensorReadingTest(sensor4,1603766249,40.1)
     */

    // 多流转换操作
    //分流,将传感器温度数据分成低温、高温两条流
    val splitStream = dataStream
      .split(data =>{
        if (data.temperature > 30.0 ) Seq("high") else Seq("low")
      })

    val highStream = splitStream.select("high")
    val lowStream = splitStream.select("low")

    val allStream = splitStream.select("high", "low")

    /**
     *
     * 数据输出样例: 大于30的都在high里面,小于30都在low
     * highStream.print("high")
     * lowStream.print("low")
     * allStream.print("all")
     *
     * all> SensorReadingTest(sensor1,1603766281,41.0)
     * high> SensorReadingTest(sensor1,1603766281,41.0)
     * all> SensorReadingTest(sensor2,1603766282,42.0)
     * high> SensorReadingTest(sensor2,1603766282,42.0)
     * all> SensorReadingTest(sensor4,1603766284,20.0)
     * low> SensorReadingTest(sensor4,1603766284,20.0)
     * all> SensorReadingTest(sensor4,1603766249,40.2)
     * high> SensorReadingTest(sensor4,1603766249,40.2)
     * all> SensorReadingTest(sensor3,1603766283,43.0)
     * high> SensorReadingTest(sensor3,1603766283,43.0)
     * all> SensorReadingTest(sensor4,1603766240,40.1)
     * high> SensorReadingTest(sensor4,1603766240,40.1)
     */

    //合流,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()
     *
     * (sensor1,41.0,warning)
     * (sensor4,healthy)
     * (sensor2,42.0,warning)
     * (sensor4,40.2,warning)
     * (sensor3,43.0,warning)
     * (sensor4,40.1,warning)
     */

    env.execute("stream test")

  }

}

class MyreduceFunction extends  ReduceFunction[SensorReadingTest]{
  override def reduce(t: SensorReadingTest, t1: SensorReadingTest): SensorReadingTest =
    SensorReadingTest(t.id, t1.timestamp, t.temperature.min(t1.temperature))
}

Datos usados ​​sensor.txt
sensor1,1603766281,41
sensor2,1603766282,42
sensor3,1603766283,43
sensor4,1603766240,40.1
sensor4,1603766284,44
sensor4,1603766249,40.2

La estructura final del código:

Flink de entrada a fragancia real (5, Flink varias operaciones de conversión de datos (transformación))

Supongo que te gusta

Origin blog.51cto.com/mapengfei/2547236
Recomendado
Clasificación