UDF开发

hive版本:1.1.0-cdh5.14.0

上次开发udf还是在培训的时候,只记得需要集成udf然后实现evaluate方法就可以了,但是用到的这个版本有了较大的改动,开发udf需要 继承genericUDF,而之前的udf也变成了弃用udf;

genericUDF必须要实现的方法:

  • initialize方法用于初始化,制定输入输出的类型
  • evaluate方法表达数据的处理逻辑
  • getDisplayString类似于java中的toString方法,在hive中以函数描述的内容展现(可以直接return children.toString()

下面记录下我这次开发的udf;

需要实现的是将ISO9601的时间格式化为东8区的时间格式,这里直接得到timestamp,代码如下:

import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.apache.hadoop.io.Text;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

public class O2FormatTime extends GenericUDF {

    //声明全局输入变量
    ObjectInspector oTime;
    //声明输出变量
    private final Text text = new Text();

    public ObjectInspector initialize(ObjectInspector[] args) throws UDFArgumentException {
        oTime = args[0];
        return PrimitiveObjectInspectorFactory.writableStringObjectInspector;
    }

    public Object evaluate(DeferredObject[] arguments) throws HiveException {
        String isoTimeStr = arguments[0].get().toString();
        if (StringUtils.isBlank(isoTimeStr)) {
            System.out.println("iso9601 time is null");
            return null;
        }

        byte[] formatedTimeStr = isoStr2utc8Str(isoTimeStr).getBytes();

        text.clear();
        text.append(formatedTimeStr,0,formatedTimeStr.length);

        return text;
    }

    public String getDisplayString(String[] children) {
        return children.toString();
    }

    /**
     * 将格式为ISO9601的时间字符串转为标准时间格式
     * @param isoStr iso9601时间字符串
     * @return 标准时间字符串
     */
    public static String isoStr2utc8Str(String isoStr){
        // TODO  解析,格式化时间字符串
        /*DateTimeFormatter isoformat = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
        DateTime dt= isoformat.parseDateTime(isoStr);

        DateTimeFormatter format = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSS");
        return dt.toString(format);*/

        // 转为东8区的时间
        /*String formatTime = DateTime.parse(isoStr)
                .withZone(DateTimeZone.forID("+08:00"))
                .toString("yyyy-MM-dd HH:mm:ss.SSS");*/

        //转换为东8区的timestamp
        long timestampL = DateTime.parse(isoStr)
                .withZone(DateTimeZone.forID("+08:00")).getMillis();

        String timestamp = String.valueOf(timestampL/1000);
        return timestamp;

    }
}

这里用到了一个jodatime的时间处理包,特别好用;

需要注意的是在定义输入和输出值类型的时候需要用hadoop的类型以便在集群中传输,比如这里的额String就需要包装成Text

猜你喜欢

转载自blog.csdn.net/bigdataprimary/article/details/82593605