Hive函数之自定义函数UDF、UDTF、UDAF

Hive自定义函数

为啥会有自定义函数
因为hive自带函数不能满足开发的需求,所以需要我们自己写hive函数,来实现一些复杂的转换或者其自身不能完成的方法。

UDF(一对一)

将输入的一个值,根据一定的转换,生成另一个格式的值。在这里UDF函数需要继承UDF类,重写evaluate(),而里面的参数根据需求传入。

public class MyUDF extends UDF {
    public String evaluate(int val){
        if(val==0){
            return "null";
        }else {
            return String.valueOf(val);
        }
    }
}

加载函数方式:

hive (default)> add jar /package/ad_release-1.0-SNAPSHOT.jar;
hive (default)> create temporary function myudtf as "com.az.udf.MyUDTF";
UDTF(一对多)

根据输入的数据,按照一定的拆分方式,将一行变多行,或者将一行变多行多列。里面有三个组件,initial、process、close三个组件,initial是返回输出的列名和类型,process是对传入的数据进行分析,传入的数据被装在一个Object的数组,得到里面每个数据然后将多行数据传给outList集合,再通过forward将数据上传。close模块则是针对在函数中会使用到一些流,比如字符流、字节流等的操作,将这些珍稀资源进行一个释放,避免资源浪费情况。

public class MyUDTF extends GenericUDTF {

    List<String> outList = new ArrayList<>();
    @Override
    public void process(Object[] objects) throws HiveException {
        //以0或1开始
        int start_with = Integer.parseInt(objects[0].toString());
        //传入日期
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = simpleDateFormat.parse(objects[1].toString());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        //确定步长
        long length = 0;
        try {
            length = (date.getTime()-simpleDateFormat.parse("1990-12-19").getTime())/(1000*60*60*24);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        if(date!=null){
            Calendar can = Calendar.getInstance();
            for(int i = start_with;i<length;i++){
                can.setTime(date);
                can.add(Calendar.DAY_OF_MONTH,i);
                System.out.println(simpleDateFormat.format(can.getTime()));

            }

        }

    }

    @Override
    public StructObjectInspector initialize(StructObjectInspector argOIs) throws UDFArgumentException {
        //1.定义输出数据列名和类型
        List<String> col1 = new ArrayList<>();
        List<ObjectInspector> col1OIs = new ArrayList<>();
        //2.添加输出数据的列明和类型
        col1.add("col1");
        col1OIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);

        return ObjectInspectorFactory.getStandardStructObjectInspector(col1,col1OIs);

    }

    @Override
    public void close() throws HiveException {

    }
}
UDAF(多对一)

比如hive的自带函数sum()和count()等聚合类函数,这个是将一张表中的多行数据进行一个汇总聚合,通过设置全局的集合来进行一个迭代的操作,操作完成后再将返回结果送回。这种函数多与group by联合使用。

public class MyUDAF extends UDAF {
    public static Logger logger = Logger.getLogger(MyUDAF.class);

    public static class Evaluator implements UDAFEvaluator{
		//定义集合来存储中间数据
        private Map<String,String> source ;
        public Evaluator(){
        	//初始化
            init();
        }
        @Override
        public void init() {
            source = new HashMap<String,String>();
        }

        public boolean iterate(String course,String score){
            if(course == null||score==null){
                return true;
            }
            source.put(course,score);
            return  true;
        }
        public Map<String,String> terminatePartial(){
            return source;
        }
        public boolean merge(Map<String,String> mapOut){
            this.source.putAll(mapOut);
            return true;
        }
        public String terminate(){
            return source.toString();
        }

    }
}
输入数据:
sc.sid	sc.cid	sc.score
1	2	99
3	4	88
1	3	55
2	1	77

sid	_c1
1	{2=99, 3=55}
2	{1=77}
3	{4=88}

public class MyUDAF extends UDAF {
    public static Logger logger = Logger.getLogger(MyUDAF.class);

    public static class Evaluator implements UDAFEvaluator{
        //定义一个List存储传入的数值
        private List<String> source ;
        //进行初始化
        public Evaluator(){
            init();
        }
        @Override
        public void init() {
            source = new ArrayList<String>();
        }

        //将每行数据值传入,如果值是空则返回,如果不为空,将其加在List里面
        public boolean iterate(String score){
            if(score==null){
                return true;
            }
            source.add(score);
            return  true;
        }
        public List<String> terminatePartial(){
            return source;
        }
        //将map的list再进行合并
        public boolean merge(List<String> listOut){
            this.source.addAll(listOut);
            return true;
        }
        //将完整的数据进行操作聚合
        public int terminate(){
            int sum = 0;
            for(String score:source){
                sum+=Integer.parseInt(score);
            }
            return sum;
        }

    }

}
输入数据:
sc.sid	sc.cid	sc.score
1	2	99
3	4	88
1	3	55
2	1	77

sid	_c1
1	144
2	77
3	88
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值