UDF:User-defined Function,用户自定义函数。一般为单输出类型,这里以scala代码为例:
/**
* @function 自定义UDF————依照姓名字符长短倒排学生姓名,并统计姓名字符长度
* @author Dongh.Wang
* 郑重声明,scala中自定义函数需继承UDF类
*/
object UDF {
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder().master("local").appName("UDF").getOrCreate()
val nameList: List[String] = List[String]("zhangsan", "lisi", "wangwu", "zhaoliu", "tianqi")
import spark.implicits._
val nameDF: DataFrame = nameList.toDF("name")
nameDF.createOrReplaceTempView("students")
nameDF.show()
spark.udf.register("STRLEN",(name:String)=>{
name.length
})
spark.sql("select name ,STRLEN(name) as length from students order by length desc").show(100)
}
}
UDAF:User- Defined Aggregation Funcation,用户定义聚合函数。注意关键词“聚合”,一般为多进单出类型;有使用数据库经验的小伙伴可以思考一下avg、sum、count、max、min这五个颇具代表性的聚合函数。
这里我们依然用scala代码来完成任务。
依然是统计学生(但例子与上面UDF并不相同),UDAF与UDF不同,它必须继承UserDefinedAggregateFunction,并重写以下8个方法:
class MyUDAF extends UserDefinedAggregateFunction {
//输入数据的类型
def inputSchema: StructType = {
DataTypes.createStructType(Array(DataTypes.createStructField("uuuu", StringType, true)))
}
/**
* 为每个分组的数据执行初始化值
*/
def initialize(buffer: MutableAggregationBuffer): Unit = {
buffer(0) = 0
}
// 每个组,有新的值进来的时候,进行分组对应的聚合值的计算
def update(buffer: MutableAggregationBuffer, input: Row): Unit = {
buffer(0) = buffer.getAs[Int](0)+1
}
// 最后merger的时候,在各个节点上的聚合值,要进行merge,也就是合并
def merge(buffer1: MutableAggregationBuffer, buffer2: Row): Unit = {
buffer1(0) = buffer1.getAs[Int](0)+buffer2.getAs[Int](0)
}
// 聚合操作时,所处理的数据的类型
def bufferSchema: StructType = {
DataTypes.createStructType(Array(DataTypes.createStructField("QQQQ", IntegerType, true)))
}
// 最后返回一个最终的聚合值要和dataType的类型一一对应
def evaluate(buffer: Row): Any = {
buffer.getAs[Int](0)
}
// 最终函数返回值的类型
def dataType: DataType = {
DataTypes.IntegerType
}
//多次运行 相同的输入总是相同的输出,确保一致性
def deterministic: Boolean = {
true
}
}
UDAF函数的调用:
object UDAF {
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder().master("local").appName("UDAF").getOrCreate()
val nameList: List[String] = List[String]("zhangsan", "lisi", "lisi", "lisi", "lisi", "wangwu",
"zhangsan", "lisi", "zhangsan", "wangwu")
import spark.implicits._
val frame: DataFrame = nameList.toDF("name")
frame.createOrReplaceTempView("students")
//select name ,count(*) from table group by name
/**
* 注册 UDAF 函数
*/
spark.udf.register("NAMECOUNT",new MyUDAF())
spark.sql("select name,NAMECOUNT(name) as count from students group by name").show(100)
}
}