前面两篇文章我们分析了UDF和UDAF的原理以及实现思路,这一节我们介绍另外一种UDF: UDTF((User-Defined Table-Generating Functions),是用来解决输入一行输出多行的需求的,本节我们来详细分析下UDTF如何实现以及如何与lateral view一起结合使用。
概述
UDTF(User-Defined Table-Generating Functions)是用来解决输入一行输出多行的需求。
执行步骤
要实现UDTF,我们需要继承org.apache.hadoop.hive.ql.udf.generic.GenericUDTF
,实现initialize
, process
, close
三个方法。
- UDTF首先会调用
initialize
方法,此方法返回UDTF的返回行的信息,返回个数,类型; - 初始化完成后,会调用process方法,真正的处理过程在process函数中,在process中,每一次forward()调用产生一行;如果产生多列可以将多个列的值放在一个数组中,然后将该数组传入到forward()函数;
- 最后close()方法调用,对需要清理的方法进行清理。
explode分析
实现分析
explode
是将hive一列中复杂的array或者map结构拆分成多行,只针对array和map两种数据结构有效。
私有变量
首先看下私有变量,inputOI
是输入参数的类型,forwardListObj
是当输入参数是List时候
@Description(name = "explode",
value = "_FUNC_(a) - separates the elements of array a into multiple rows,"
+ " or the elements of a map into multiple rows and columns ")
public class GenericUDTFExplode extends GenericUDTF {
private transient ObjectInspector inputOI = null;
private transient final Object[] forwardListObj = new Object[1];
private transient final Object[] forwardMapObj = new Object[2];
}
initialize
initialize
初始化函数会对输入参数进行检查,输入参数长度是1,然后初始化输入类型,输出名字以及类型:
- 如果category是List,则初始化
inputOI
类型,然后初始化结果的变量名字为col,并设置结果的类型; - 如果category是Map,则初始化
inputOI
类型,然后初始化结果的变量名字为key, value,并设置结果的类型key类型和value类型.
@Override
public StructObjectInspector initialize(ObjectInspector[] args) throws UDFArgumentException {
if (args.length != 1) {
throw new UDFArgumentException("explode() takes only one argument");
}
ArrayList<String> fieldNames = new ArrayList<String>();
ArrayList<ObjectInspector> fieldOIs = new ArrayList<ObjectInspector>();
switch (args[0].getCategory()) {
case LIST:
inputOI = args[0];
fieldNames.add("col");
fieldOIs.add(((ListObjectInspector)inputOI).getListElementObjectInspector());
break;
case MAP:
inputOI = args[0];
fieldNames.add("key");
fieldNames.add("value");
fieldOIs.add(((MapObjectInspector)inputOI).getM