解析Hive复杂字段3--GenericUDF

前言

前两篇文章针对同一个解析Hive复杂字段的需求分别采用了Hive 自带函数(lateral view ,explode,正则表达式)和简单UDF的方式来实现,在采用简单UDF方式处理的时候发现,UDF函数返回的必须是Hive的基本类型,如Text,IntWritable,DoubleWritable,LongWritable等,具体在此次需求中UDF返回的是字符串,每个HotelId用逗号分隔,在真正使用时,仍需要通过split函数拆分成数组形式。

本篇文章就是在上一篇简单UDF的基础上,通过继承GenericUDF的方式,直接返回array类型的结果

Hive GenericUDF

GenericUDF实现比较复杂,需要先继承GenericUDF。这个API需要操作Object Inspectors,并且要对接收的参数类型和数量进行检查。GenericUDF需要实现以下三个方法:

//这个方法只调用一次,并且在evaluate()方法之前调用,该方法接收的参数是一个ObjectInspectors数组,该方法检查接收正确的参数类型和参数个数
abstract ObjectInspector initialize(ObjectInspector[] arguments);

//这个方法类似evaluate方法,处理真实的参数,返回最终结果
abstract Object evaluate(GenericUDF.DeferredObject[] arguments);

//此方法用于当实现的GenericUDF出错的时候,打印提示信息,提示信息就是该方法的返回的字符串
abstract String getDisplayString(String[] children);

实例

import java.util.ArrayList;
import java.util.Date;

import net.sf.json.JSONObject;
import net.sf.json.JSONArray;
import org.apache.hadoop.hive.ql.exec.MapredContext;
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache,hadoop.hive.ql.udf.generic.GenericUDF;
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.primitive.PrimitiveObjectInspectorFactory;

//继承GenericUDF
public class GetHotelidSenior extends GenericUDF{
    private static int mapTasks=0;
    private static String init="";
    private transient ArrayList<Integer> ret=new ArrayList<Integer>();//存放返回list

    @Override
    public void configure(MapredContext context){
        System.out.println(new Date()+"###### configure");
        if(null!=context){
            //从jobconf中获取map数
            mapTasks=context.getJobConf().getNumMapTasks();
        }
        System.out.println(new Date()+"###### mapTasks["+mapTasks+"]..");
    }

    @Override
    public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException{
        System.out.println(new Date()+"##### initialize");
        //初始化文件系统,可以在这里初始化读取文件
        init="init";
        //定义函数的返回类型为Java的list
        ObjectInspector returnOi=PrimitiveObjectInspectorFactory.getPrimitiveJavaObjectInspector(PrimitiveObjectInspector.PrimitiveCategory.INT);
        return ObjectInspectorFactory.getStandardListObjectInspector(returnOi);
    }

    @Override
    public Object evaluate(GenericUDF.DeferredObject[] args) throws HiveException{
        ret.clear();
        try {
            JSONObject jb=JSONObject.fromObject(args[0].get().toString());
            JSONArray ja=jb.getJSONArray("htllist");
            for (int i = 0; i < ja.size(); i++) {
                JSONObject jbi = ja.getJSONObject(i);
                if (jbi.has("hotelid")) {
                    ret.add(jbi.getInt("hotelid"));
                }
            }
        }catch (net.sf.json.JSONException ex){
            return null;

        }
        return ret;
    }

    @Override
    public String getDisplayString(String[] str){
        return "Usage:GetHotelIdSenior(String str)";
    }
}

小结

这篇和上一篇文章结合起来看,当写Hive UDF时,有两个选择:分别是继承UDF类和继承抽象类GenericUDF。这两种方法不同之处在于GenericUDF可以处理复杂类型参数,并且继承GenericUDF更加有效率。

解析Hive复杂字段2–UDF

    原文作者:风筝flying
    原文地址: https://www.jianshu.com/p/ba0e54579cc4
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞