Hive的自定义函数,分为三种:UDF、UDAF、UDTF

UDF:User Defined Functions,自定义函数,用来处理,输入一行,输出一行的操作,类似MapReduce中Map操作
UDAF:User Defined Aggregation Functions,自定义聚合函数,用来处理输入多行,输出一行的操作,类似MapReduce中Reduce操作
UDTF:User Defined Table Generating Functions,自定义表产生函数,用来处理输入一行,输出多行的操作

UDF开发
UDF开发相对比较简单,但是实现起来,通常有两种方式:

继承基础的UDF接口:函数读取和返回基本类型,即Hadoop和Hive的基本类型。如,Text、IntWritable、LongWritable、DoubleWritable等。
继承复杂的GenericUDF接口,除了上述的,还可以处理Map、List、Set类型。

GenericUDF 需要重写以下三个方法:
//这个方法只调用一次,并且在evaluate()方法之前调用。该方法接受的参数是一个ObjectInspectors数组。该方法检查接受正确的参数类型和参数个数。
ObjectInspector initialize(ObjectInspector[] arguments);

//这个方法类似UDF的evaluate()方法。它处理真实的参数,并返回最终结果。  
Object evaluate(GenericUDF.DeferredObject[] arguments);  
  
//这个方法用于当实现的GenericUDF出错的时候,打印出提示信息。而提示信息就是你实现该方法最后返回的字符串。  
String getDisplayString(String[] children);

区别
以上两种实现不同之处是:GenericUDF 可以处理复杂类型参数,并且继承GenericUDF更加有效率,因为UDF class 需要HIve使用反射的方式去实现。 UDF是作用于一行的。
但是在使用过程中需要依赖JAVA反射机制,因此性能相对较低

UDAF开发
hive有两种UDAF:Simple和Generic。
Simple。即继承org.apache.hadoop.hive.ql.exec.UDAF类,并在派生类中以静态内部类的方式实现org.apache.hadoop.hive.ql.exec.UDAFEvaluator接口。这种方式简单直接,但是在使用过程中需要依赖JAVA反射机制,因此性能相对较低。在Hive源码包org.apache.hadoop.hive.contrib.udaf.example中包含几个示例。。但是这些接口已经被注解为Deprecated,建议不要使用这种方式开发新的UDAF函数。
Generic。这是Hive社区推荐的新的写法,以抽象类代替原有的接口。新的抽象类org.apache.hadoop.hive.ql.udf.generic.AbstractGenericUDAFResolver替代老的UDAF接口,新的抽象类org.apache.hadoop.hive.ql.udf.generic.GenericUDAFEvaluator替代老的UDAFEvaluator接口。

UDAF是需要在hive的sql语句和group by联合使用,hive的group by对于每个分组,只能返回一条记录,这点和mysql不一样

Hive开发有两个步骤:

编写resolver类,resolver负责类型检查,操作符重载。类继承org.apache.hadoop.hive.ql.udf.generic.AbstractGenericUDAFResolver,AbstractGenericUDAFResolver实现了org.apache.hadoop.hive.ql.udf.generic.GenericUDAFResolver2,方便统一接口。
第二个是编写evaluator类。evaluator真正实现UDAF的逻辑。通常来说,实现org.apache.hadoop.hive.ql.udf.generic.GenericUDAFEvaluator ,包括几个必须实现的抽象方法,这几个方法负责完成UDAF所需要处理的逻辑。

UDTF开发

编码实现:
UDTF函数的实现必须通过继承抽象类GenericUDTF,并且要实现initialize, process,close 函数。
1. hive将通过initialize方法来获取UDTF函数要求的参数类型然后返回与UDTF函数输出行对象相应的Inspector。initialize使用PrimitiveObjectInspector来解析输入的数据,同时定义输出对象Inspector所需要的field。
2. 函数实现具体的数据解析过程,在通过stringIO获取输入字段,程序中使用parseInputRecord方法将json字符串解析成多个字符,将返回一个List完成一行转多行的任务。最后forward将多行数据做udtf函数的输出。
3. close函数

Spark 自定义UDF函数

一、UDF函数

  1. UDF
    首先定义UDF函数,那么创建一个SqlUdf类,并且继承UDF1或UDF2等等,UDF后边的数字表示了当调用函数时会传入进来有几个参数
  2. 重写 call 方法
  3. 注册UDF sparkSession.udf.register
    //第三个参数是返回类型
    sparkSession.udf.register(“splicing_t1_t2”,new SqlUDF,DataTypes.StringType)

二、无类型的用户自定于聚合函数:UserDefinedAggregateFunction UDAF

class AvgAge extends UserDefinedAggregateFunction {
 //设置输入数据的类型,指定输入数据的字段与类型,它与在生成表时创建字段时的方法相同
 override def inputSchema: StructType = ???
 //指定缓冲数据的字段与类型
 override def bufferSchema: StructType = ???
 //指定数据的返回类型
 override def dataType: DataType = ???
 //指定是否是确定性,对输入数据进行一致性检验,是一个布尔值,当为true时,表示对于同样的输入会得到同样的输出
 override def deterministic: Boolean = ???
 //initialize用户初始化缓存数据
 override def initialize(buffer: MutableAggregationBuffer): Unit = ???
 //当有新的输入数据时,update就会更新缓存变量
 override def update(buffer: MutableAggregationBuffer, input: Row): Unit = ???
 //将更新的缓存变量进行合并,有可能每个缓存变量的值都不在一个节点上,最终是要将所有节点的值进行合并才行
 override def merge(buffer1: MutableAggregationBuffer, buffer2: Row): Unit = ???
 //一个计算方法,用于计算我们的最终结果
 override def evaluate(buffer: Row): Any = ???
 }sparkSession.udf.register(“splicing_t1_t2”,new SqlUDF)

三、类型安全的用户自定于聚合函数:Aggregator UDAF
1. 而使用此聚合函数就不能通过注册函数来使用了,需要通过Dataset对象的select来使用
2. 因此无类型的用户自定于聚合函数:UserDefinedAggregateFunction和类型安全的用户自定于聚合函数:Aggregator之间的区别是
(1)UserDefinedAggregateFunction不能够带类型而Aggregator是可以带类型的。
(2)使用方法不同UserDefinedAggregateFunction通过注册可以在DataFram的sql语句中使用,而Aggregator必须是在Dataset上使用。

三 UDTF 走Hive Spark 好像没找到相关的资料