HIVE自定义UDTF函数

55 篇文章 1 订阅
46 篇文章 2 订阅

UDTF函数

HIVE提供了丰富的内置函数,但是对于一些复杂逻辑还是需要自定义函数来实现,对此,HIVE也提供了一些自定义的接口和类。
UDF:一进一出,一对一的关系数据
UDTF:一进多处,一对多的关系数据
UDAF:多进一出,多对一的关系数据

一、继承GenericUDTF类

实现三个方法:

initialize方法

两个作用:

  1. 初始化参数,判断参数类型是否符合要求

  2. 设置输出列和类型

    ArrayList<String> fieldNames = new ArrayList<String>();
    ArrayList<ObjectInspector> fieldOIs = new ArrayList<ObjectInspector>();
    
    fieldNames.add("col1");  // 列名为col1
    fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);  // 类型String
    fieldNames.add("col2");
    fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
    
process方法

处理数据,通过forward方法将数据写出,没写出一次,代表为一行,可以传入一个数组

forward(result);
close方法

顾名思义,打扫干净,下一位

二、源码解析

因为在之前的版本UDTF的initialize方法提供的是:

@Override
public StructObjectInspector initialize(ObjectInspector[] argOIs) throws UDFArgumentException {
  return super.initialize(argOIs);
}

现在上述的方式已经不推荐了,改作了:

@Override
public StructObjectInspector initialize(StructObjectInspector argOIs) throws UDFArgumentException {

return super.initialize(argOIs);
}

将一个参数数组转变为了一个结构对象检查器,这个怎么使用的?

看一下super的实现:

public StructObjectInspector initialize(StructObjectInspector argOIs)
      throws UDFArgumentException {
  List<? extends StructField> inputFields = argOIs.getAllStructFieldRefs();
  ObjectInspector[] udtfInputOIs = new ObjectInspector[inputFields.size()];
  for (int i = 0; i < inputFields.size(); i++) {
    udtfInputOIs[i] = inputFields.get(i).getFieldObjectInspector();
  }
  return initialize(udtfInputOIs);
}

如果需要校验参数类型,通过size方法校验长度,通过getTypeName方法校验类型

//对输入参数个数进行进行检验
if (argOIs.getAllStructFieldRefs().size()!=1) {
        throw new UDFArgumentException ("args must be 1");
    }
//对输入参数的类型校验
    if(!"string".equals(argOIs.getAllStructFieldRefs().get(0).getFieldObjectInspector().getTypeName().toLower())){
        throw new  UDFArgumentException("args type must be string");
     }

其实就是将参数列表封装成了StructObjectInspector对象,如果想要校验参数,那么通过上述的方式,可以看到,调用getAllStructFieldRefs方法,获取所有的输入列列表,遍历就可以取到参数列表了

inputFields.get(i).getFieldObjectInspector();

process方法就是处理逻辑的方法,每次输出一个forward,就会分割为一列

String[] result = comment.split(":");
forward(result);

三、例子

按照逗号进行分割字符串,输出列

public class ExplodeArray extends GenericUDTF {
    public StructObjectInspector initialize(StructObjectInspector argOIs) throws UDFArgumentException {
        //定义返回值名称
        List<String> filedNames = new ArrayList<String>();
        //校验返回值类型
        List<ObjectInspector> filedOIs= new ArrayList<ObjectInspector>();
        filedNames.add("col1");
           filedOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
        return  ObjectInspectorFactory.getStandardStructObjectInspector(filedNames,filedOIs);
    }

    public void process(Object[] objects) throws HiveException {
        String comment= objects[0].toString();
        String[] str = comment.split(",");
		for(String s : str){
		    forward(s);
		}
    }

    public void close() throws HiveException {

    }
}

注意在UDTF函数中,会出现传入数据异常的问题,在这里我并没有校验参数,在实际生产中是需要校验参数的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

牧码文

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值