美文网首页
解析Hive复杂字段3--GenericUDF

解析Hive复杂字段3--GenericUDF

作者: 风筝flying | 来源:发表于2018-08-30 16:05 被阅读264次

    前言

    前两篇文章针对同一个解析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

    相关文章

      网友评论

          本文标题:解析Hive复杂字段3--GenericUDF

          本文链接:https://www.haomeiwen.com/subject/jfkfwftx.html