DataSet API编程指南之Transformations(四)


Flink 程序是实现了分布式集合转换(例如过滤、映射、更新状态、join、分组、定义窗口、聚合)的规范化程序。Transformation将一个或多个数据集转换为新数据集。程序可以将多个转换组合成复杂的程序集。

本节简要概述可用的Transformation。Transformations文档提供了所有转换的完整描述和示例。

1、Map

作用:返回一个新的DataSet,该DataSet由每一个输入元素经过func函数转换后组成。map函数实现了一对一的映射,也就是说,func函数必须返回一个元素。

data.map { x => x.toInt } // 将数据集中的每一个元素转成Int类型

例子:

/** 功能:将数据集中的每个元素 * 2 */
def mapFunction(env:ExecutionEnvironment) = {
    val data: DataSet[Int] = env.fromCollection(List(1, 2, 3))
    // 每个元素*2
    data.map(_ * 2).print() // 方式一:最重要方式
    data.map(x => x * 2).print()    // 方式二
    data.map((x:Int) => {   // 方式三
        x * 2
    }).print()
    data.map((x) => {   // 方式四
        x * 2
    }).print()
}

2、FlatMap

作用:类似于map,但是每一个输入元素可以被映射为0或多个输出元素(所以func应该返回一个序列,而不是单一元素)

/** 功能:将数据集中的每个元素通过空格进行分割 */
def flatMapFunction(env:ExecutionEnvironment) = {
    val info: ListBuffer[String] = ListBuffer[String]()
    info.append("hadoop spark")
    info.append("zookeeper kafka")
    info.append("flink blink")
    val data: DataSet[String] = env.fromCollection(info)
    data.flatMap(_.split(" "))
            .map((_, 1))
            .groupBy(0)
            .sum(1)
            .print()
}

3、MapPartition

作用:类似于map,但独立地在DataSet的每一个分区上运行,因此在类型为T的DataSet上运行时,func的函数类型必须是Iterator[T]) => TraversableOnce[R]。假设有N个元素,有M个分区,那么map的函数的将被调用N次,而mapPartition被调用M次

map()和mapPartition()的区别:

  • map():每次处理一条数据。
  • mapPartition():每次处理一个分区的数据,这个分区的数据处理完后,原DataSet中分区的数据才能释放,可能导致OOM。
  • 开发指导:当内存空间较大的时候建议使用mapPartition(),以提高处理效率。
/** 功能:计算每个分区中元素的个数 */
def mapPartitionFunction(env:ExecutionEnvironment) = {
    val info: ListBuffer[String] = ListBuffer[String]()
    info.append("hadoop spark")
    info.append("zookeeper kafka")
    info.append("hive")
    info.append("zookeeper")
    info.append("hbase")
    info.append("spark")
    val data: DataSet[String] = env.fromCollection(info).setParallelism(3)
    data.mapPartition { in => Some(in.size) }.print()
}

4、Filter 过滤

作用:过滤。返回一个新的DataSet,该DataSet由经过func函数计算后返回值为true的输入元素组成。

data.filter { _ > 1000 }	// 筛选值>1000的元素

例子:

def filterFunction(env:ExecutionEnvironment) = {
    val data: DataSet[Int] = env.
    					fromCollection(List(1, 2, 3))
    data.filter(_ % 2 == 0).print()
}

5、Reduce

作用:通过用户自定义的func函数聚集DataSet中的所有元素,先聚合分区内数据,再聚合分区间数据。

def reduceFunction(env:ExecutionEnvironment) = {
    val data: DataSet[Int] = env
            .fromCollection(List(1, 2, 3)).setParallelism(2)
    data.reduce(_ + _).print()	// 计算所有元素的和
}

6、ReduceGroup

作用:将一组元素组合为一个或多个元素。ReduceGroup可以应用于一个完整的数据集或一个分组的数据集。

def reduceGroupFunction(env:ExecutionEnvironment) = {
    val info: ListBuffer[(Int, String)] = ListBuffer[(Int, String)]()
    info.append((1, "hadoop"))
    info.append((1, "spark"))
    info.append((1, "hadoop"))
    info.append((2, "spring"))
    info.append((2, "java"))
    info.append((3, "linux"))
    info.append((4, "vue"))
    val data: DataSet[(Int, String)] = env.fromCollection(info)
    data.groupBy(0)
            .reduceGroup(in => {
                in.reduce((x, y) => (x._1, x._2 + ", " + y._2))
            })
            .print()
     // 输出格式: (1,hadoop, spark, hadoop)
}

7、Aggregate

作用:聚合操作。

Aggregate操作只能应用在元组DataSet中,并且仅仅支持position key进行分组。

例子:根据第二个字段进行分组,在分组中根据第一个字段求和,第三个字段取最小值。

def aggregateFunction(env:ExecutionEnvironment) = {
    val list = List(Tuple3(1, "hadoop", 1.0), Tuple3(2, "spark", 1.5), Tuple3(3, "zookeeper", 2.0), Tuple3(5, "zookeeper", 3.0))
    val input: DataSet[(Int, String, Double)] = env.fromCollection(list)
    input.groupBy(1)
            .aggregate(Aggregations.SUM, 0)
            .and(Aggregations.MIN, 2).print()
}
// 输出结果
// (1,hadoop,1.0)
// (8,zookeeper,2.0)
// (2,spark,1.5)

8、Distinct

作用:去重。对源DataSet进行去重后,返回一个新的DataSet。

def distinctFunction(env:ExecutionEnvironment) = {
    val info: ListBuffer[String] = ListBuffer[String]()
    info.append("hadoop")
    info.append("kafka")
    info.append("hadoop")
    val data: DataSet[String] = env.fromCollection(info)
    data.distinct()
            .print()
}

9、Join

作用:获取两个DataSet中字段匹配关系的记录。两个数据集的元素通过一个或多个键连接,可以使用如下四种key类型:

  • a key expression
  • a key-selector function
  • one or more field position keys (Tuple DataSet only).
  • Case Class Fields
def joinFunction(env:ExecutionEnvironment) = {
    val info1: ListBuffer[(Int, String)] = ListBuffer[(Int, String)]()
    info1.append((1, "hadoop"))
    info1.append((2, "spark"))
    val info2: ListBuffer[(String, String)] = ListBuffer[(String, String)]()
    info2.append(("apache", "hadoop"))
    info2.append(("apache", "spark"))
    info2.append(("apache", "zookeeper"))
    val data1: DataSet[(Int, String)] = env.fromCollection(info1)
    val data2: DataSet[(String, String)] = env.fromCollection(info2)

    data1.join(data2).where(1).equalTo(1)
            .apply((first, second) => {
                (first._1, second._1, first._2)
            }).print()
    // 输出: (编号, 公司, 框架名称)
}

10、OuterJoin

与MySQL中的外连接相对应。OuterJoin转换对两个数据集执行左、右或完全的外连接。

OuterJoins 只支持Java and Scala DataSet API.

11、CoGroup

12、Cross

作用:计算两个DataSet的笛卡尔积。

def crossFunction(env:ExecutionEnvironment) = {
    val list1 = List("hadoop", "spark")
    val list2 = List(1, 2)
    val data1: DataSet[String] = env.fromCollection(list1)
    val data2: DataSet[Int] = env.fromCollection(list2)
    data1.cross(data2).print()
}

13、Union

作用:求两个DataSet的交集。

14、Rebalance

rebalance将以循环方式分发数据,均匀地重新平衡每个分区上的数据,避免数据倾斜。

Note: 该函数只能应用在map此类方法之前。

def rebalanceFunction(env:ExecutionEnvironment) = {
    val data: DataSet[Int] = env
            .fromCollection(List(1, 2, 3)).setParallelism(2)
    data.rebalance().map((_, 1)).print()
}

15、Hash-Partition

根据指定的key进行hash分区。key可以是指定的索引位置、表达式、key选择器。

例子:

val in: DataSet[(Int, String)] = // [...]
val result = in.partitionByHash(0).mapPartition { ... }

16、Range-Partition

根据指定的key进行range分区。key可以是指定的索引位置、表达式、key选择器。

例子:

val in: DataSet[(Int, String)] = // [...]
val result = in.partitionByRange(0).mapPartition { ... }

17、Custom Partitioning

作用:使用自定义分区函数根据指定的key将记录分配给特定的分区。key可以指定为位置键、表达式键和键选择器函数。

注意:此方法只适用于单个字段的键。

val in: DataSet[(Int, String)] = // [...]
val result = in
  .partitionCustom(partitioner, key).mapPartition { ... }

18、Sort Partition

作用:在指定字段上按指定的顺序对数据集的所有分区进行本地排序。字段可以指定为元组位置或字段表达式。对多个字段进行排序是通过链接sortPartition()调用完成的。

val in: DataSet[(Int, String)] = // [...]
// 根据字段1进行升序排序
val result = in.sortPartition(1, Order.ASCENDING).mapPartition { ... }

19、First-n

作用:返回一个DataSet中的前n个元素。

def firstNFunction(env:ExecutionEnvironment) = {
    val info: ListBuffer[(Int, String)] = ListBuffer[(Int, String)]()
    info.append((1, "hadoop"))
    info.append((1, "spark"))
    info.append((1, "flink"))
    info.append((2, "spring"))
    info.append((2, "java"))
    info.append((3, "linux"))
    info.append((4, "vue"))
    val data: DataSet[(Int, String)] = env
            .fromCollection(info)
    // 1、取前2个元素
    data.first(2).print()
    // 2、根据第一个字段分组,并取每个分组中的前2个元素
    data.groupBy(0)
            .first(2).print()
    // 3、根据第一个字段分组,并根据第二个字段倒序排序,并获取每个分组中的前2个元素
    data.groupBy(0).sortGroup(1, Order.DESCENDING)
            .first(2).print()
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值