自定义函数的类前面的注释,会在hive中desc中显示自定义函数的doc @Description( name = "myudf", value = "这是一个自定义方法", extended = "eg: select myudf(1,2) => 3 , select myudf(\"hello\",\"world\") => helloworld" )
导入包:hive-exec
1.UDF //user define function
//输入单行,输出单行,类似于 format_number(age,'000')
继承UDF 重新方法
import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDF;
@Description(
name = "myudf",
value = "",
extended = "eg: select myudf(1,2) => 3 , select myudf(\"hello\",\"world\") => helloworld"
)
public class MyUDF extends UDF {
public int evaluate(int i , int j){
return i+j;
}
public String evaluate(String a, String b){
return a+b;
}
}
2.UDTF //user define table-gen function
//输入单行,输出多行,类似于 explode(array);
1、通过initialize的参数(方法参数)类型或参数个数,
2、返回输出表的表结构(字段名+字段类型)
3、通过process函数,取出参数值,
4、进行处理后通过forward函数将其输出
实现方法:继承GenericUDTF,实现initialize和process方法.,其中initialize方法里返回值定义了表结构,也就是函数执行完成之后定义为了一个新的虚拟的表,StructObjectInspector也就是结构对象,initialize方法的参数argOIs是输入字段的字段类型.而process是函数中真正生成数据的阶段.
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import java.util.ArrayList;
import java.util.List;
public class MyUDTF extends GenericUDTF {
PrimitiveObjectInspector poi;
//定义了表结构
//argOIs => 输入字段的字段类型
@Override
public StructObjectInspector initialize(StructObjectInspector argOIs) throws UDFArgumentException {
if (argOIs.getAllStructFieldRefs().size() != 1) {
throw new UDFArgumentException("参数个数只能为1");
}
//如果输入字段类型非String,则抛异常
ObjectInspector oi = argOIs.getAllStructFieldRefs().get(0).getFieldObjectInspector();//获取所有输入参数中的第//一个参数
if (oi.getCategory() != ObjectInspector.Category.PRIMITIVE) {
throw new UDFArgumentException("参数非基本类型,需要基本类型string");
}
//强转为基本类型对象检查器
poi = (PrimitiveObjectInspector) oi;
if (poi.getPrimitiveCategory() != PrimitiveObjectInspector.PrimitiveCategory.STRING) {
throw new UDFArgumentException("参数非string,需要基本类型string");
}
//构造表的字段名name
List<String> fieldNames = new ArrayList<String>();
fieldNames.add("name");
//构造字段类型,string
List<ObjectInspector> fieldOIs = new ArrayList<ObjectInspector>();
//通过基本数据类型工厂获取java基本类型oi
fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
//构造对象检查器
return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames,
fieldOIs);
}
//生成数据阶段
@Override
public void process(Object[] args) throws HiveException {
//得到一行数据
String line = (String) poi.getPrimitiveJavaObject(args[0]);
String[] arr = line.split(" ");
for(String name:arr){
Object[] objs = new Object[1];
objs[0] = name;//如果表的字段有多个时,objs[1] = xxx,init中表结构决定的
forward(objs);//通过forward 将数据发送出去到定义的表结构中去
}
}
//do nothing
@Override
public void close() throws HiveException {
}
}
3.UDAF //user define aggr function
//输入多行,输出单行,类似于 sum(xxx)
注册自定义函数的三种方式:
1、create function xxx as '自定义类的全路径';
2、create temporary function xxx as '自定义类的全路径'; //临时自定义函数,重启hive之后不再发挥作用
3、create function xxx as '' using jar 'hdfs://mycluster/xxx.jar'; //jar在hdfs上的位置