java udtf 递归_UDF开发手册 - UDTF

本文详细介绍了如何使用Java开发Hive的用户定义表生成函数(UDTF),特别是如何实现递归UDTF。内容包括初始化方法initialize()的参数检查和返回值类型设定,核心处理方法process()的参数接收、逻辑实现和结果输出,以及在所有输入处理完后调用的close()方法。
摘要由CSDN通过智能技术生成

表生产函数

一行输入,输出多行结果

实现 自定义UDTF 需要继承 GenericUDTF,并且实现其三个方法:

initialize()

process()

close()

其中 process()、close() 为 GenericUDTF 中的抽象方法,必须实现。initialize() 虽然不是抽象方法,但必须手动覆盖实现该方法,因为 GenericUDTF 的 initialize() 最终会抛出一个异常:

throw new IllegalStateException("Should not be called directly");

复制代码

initialize()

需要覆盖实现的方法如下:

public StructObjectInspector initialize(StructObjectInspector argOIs)

throws UDFArgumentException{ }

复制代码

initialize() 在函数在 GenericUDTF 初始化时被调用一次,执行一些初始化操作,包括:

判断函数参数个数

判断函数参数类型

确定函数返回值类型

除此之外,用户在这里还可以做一些自定义的初始化操作,比如初始化HDFS客户端等

其一:判断函数参数个数

initialize() 的参数为 StructObjectInspector argOIs

可以通过如下方式获取 自定义UDTF 的所有参数

List extends StructField> inputFieldRef = argOIs.getAllStructFieldRefs();

复制代码

判断参数个数的方式很简单,只要判断 inputFieldRef 的元素个数即可

示例:

List extends StructField> inputFieldRef = argOIs.getAllStructFieldRefs();

// 参数个数为1

if (inputFieldRef.size() != 1)

throw new UDFArgumentException("需要一个参数");

复制代码

其二:判断函数参数类型

inputFieldRef 的元素类型是 StructField,可以通过 StructField 获取参数类型 ObjectInspector

ObjectInspector 类型的判断方法可以参考 《UDF开发手册 - UDF》

判断参数个数和类型的示例:

// 1. 判断参数个数,只有一个参数

List extends StructField> inputFieldRef = argOIs.getAllStructFieldRefs();

if (inputFieldRef.size() != 1)

throw new UDFArgumentException("需要一个参数");

// 2. 判断参数类型,参数类型为string

ObjectInspector objectInspector = inputFieldRef.get(0).getFieldObjectInspector();

if (objectInspector.getCategory() != ObjectInspector.Category.PRIMITIVE // 参数是Hive原始类型

|| !PrimitiveObjectInspector.PrimitiveCategory.STRING.equals(((PrimitiveObjectInspector)objectInspector).getPrimitiveCategory())) // 参数是Hive的string类型

throw new UDFArgumentException("函数第一个参数为字符串"); // 当自定义UDF参数与预期不符时,抛出异常

复制代码

其三:确定函数返回值类型

UDTF函数可以对于一行输入,可以产生多行输出,并且每行结果可以有多列。 自定义UDTF 的返回值类型会稍微复杂些,需要明确输出结果的所有列名和列类型

initialize() 方法的返回值类型为 StructObjectInspector

StructObjectInspector 表示了一行记录的结构,可以包括多个列。每个列有列名、列类型和列注释(可选)

可以通过 ObjectInspectorFactory 来获取 StructObjectInspector 实例:

/**

* structFieldNames:列

*/

ObjectInspectorFactory.getStandardStructObjectInspector(

List structFieldNames,

List structFieldObjectInspectors)

复制代码

structFieldNames的第n个元素,代表了第n列的名称;structFieldObjectInspectors的第n个元素,代表了第n列的类型。

structFieldNames 和 structFieldObjectInspectors 应该保持长度一致

// 只有一列,列的类型为Map

return ObjectInspectorFactory.getStandardStructObjectInspector(

Collections.singletonList("result_column_name"),

Collections.singletonList(

ObjectInspectorFactory.getStandardMapObjectInspector(

PrimitiveObjectInspectorFactory.javaStringObjectInspector, // Key 是 String

PrimitiveObjectInspectorFactory.javaIntObjectInspector // Value 是 int

)

)

);

复制代码

process()

核心方法,自定义UDTF 的实现逻辑

代码实现步骤可以分为三部分:

参数接收

自定义UDTF核心逻辑

输出结果

/**

* Give a set of arguments for the UDTF to process.

*

* @param args

* object array of arguments

*/

public abstract void process(Object[] args) throws HiveException;

复制代码

第一步:参数接收

args 即是 自定义UDTF 的参数,传入的参数不同,会是不同的Java类型,以下是Hive常用参数类型对应的Java类型

Hive类型Java类型tinyintByteWritable

smallintShortWritable

intIntWritable

bigintLongWritable

stringText

booleanBooleanWritable

floatFloatWritable

doubleDoubleWritable

ArrayArrayList

MapHashMap

参数接收示例:

// 参数null值的特殊处理

if (args[0] == null)

return;

// 接收参数

String str = ((Text) args[0]).toString();

复制代码

第二步:自定义UDTF核心逻辑

获取参数之后,到这里就是自由发挥了~

第三步:输出结果

process() 方法本身没有返回值,通过 GenericUDTF 中的 forward() 输出一行结果。forward() 可以反复调用,可以输出任意行结果

/**

* Passes an output row to the collector.

*

* @param o

* @throws HiveException

*/

protected final void forward(Object o) throws HiveException {

collector.collect(o);

}

复制代码

forward() 可以接收 List 或 Java数组,第n个元素代表第n列的值

List list = new LinkedList<>();

// 第一列是int

list.add(1);

// 第二列是string

list.add("hello");

// 第三列是boolean

list.add(true);

// 输出一行结果

forward(list);

复制代码

close()

没有其他输入行时,调用该函数

可以进行一些资源关闭处理等最终处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值