自定义udaf函数的代码框架

 //首先继承一个类AbstractGenericUDAFResolver,然后实现里面的getevaluate方法
public GenericUDAFEvaluator getEvaluator(TypeInfo[] parameters) throws SemanticException {} //在类里面再定义一个内部类继承GenericUDAFEvaluator并重写里面的几个方法 public ObjectInspector init(Mode m, ObjectInspector[] parameters) throws HiveException; abstract AggregationBuffer getNewAggregationBuffer() throws HiveException; public void reset(AggregationBuffer agg) throws HiveException; public void iterate(AggregationBuffer agg, Object[] parameters) throws HiveException; public Object terminatePartial(AggregationBuffer agg) throws HiveException; public void merge(AggregationBuffer agg, Object partial) throws HiveException; public Object terminate(AggregationBuffer agg) throws HiveException; //方法的具体使用说明在实例代码中说明

自己实现count聚合函数java代码

public class Sum extends AbstractGenericUDAFResolver {
//创建log对象,用于抛出错误和异常
static final Log log = LogFactory.getLog(Sum.class.getName()); //判断sql语句传入的参数的个数和类型,并将其返回相应的类型
@Override
public GenericUDAFEvaluator getEvaluator(TypeInfo[] info) throws SemanticException {
//判断参数的个数是否符合要求
if (info.length != 1) {
throw new UDFArgumentTypeException(info.length - 1, "exactly one parameter expected");
} //判断传入的参数类型
if (info[0].getCategory() != ObjectInspector.Category.PRIMITIVE) {
throw new UDFArgumentTypeException(0, "only primitive argument is expected but " +
info[0].getTypeName() + "is passed");
} //对传入的参数类型进行进一步的判断是否是我们需求的数据的类型
switch (((PrimitiveTypeInfo) info[0]).getPrimitiveCategory()) {
case BYTE:
case SHORT:
case INT:
case LONG:
case FLOAT:
case DOUBLE:
return new SumRes();
default:
throw new UDFArgumentTypeException(0, "only numric type is expected but " + info[0].getTypeName() + "is passed");
}
} public static class SumRes extends GenericUDAFEvaluator { //创建变量存储中间结果
//input:每一步执行时传入的参数
//output:每一步执行时输出的结果数据的类型
//input和output都只是指定的输入输出的数据类型而已,和数据计算本身无关
//result是聚合的结果的数据,和用于particial2和final阶段的结果输出,genuine不同的业务要求指定不同的类型等
private PrimitiveObjectInspector input;
private PrimitiveObjectInspector output;
private LongWritable result; //对各个阶段都会首先调用一下该方法,并且对输入输出数据初始化 /**
*Mode:
* partial1 : map阶段 会调用 init -> iterate -> partialterminate
* partial2 : combiner阶段 会调用 init -> merge -> partialterminate
* final : reduce阶段 会调用 init -> merge -> terminate
* complete : 只有map没有reduce阶段 会调用 init -> iterate -> terminate
*/
@Override
public ObjectInspector init(Mode m, ObjectInspector[] parameters) throws HiveException {
assert parameters.length == 1;
super.init(m,parameters); //init input
//将传入的参数赋值给定义的input输入变量
if (m == Mode.PARTIAL1 || m == Mode.COMPLETE) {
input = (PrimitiveObjectInspector)parameters[0];
}else {
input = (PrimitiveObjectInspector)parameters[0];
} //init output
//返回中间聚合,或最终结果的数据的类型
if (m == Mode.PARTIAL1 || m == Mode.COMPLETE) {
output = PrimitiveObjectInspectorFactory.writableLongObjectInspector;
}else {
output = PrimitiveObjectInspectorFactory.writableLongObjectInspector;
}
//result用于实际接收聚合结果数据
result = new LongWritable();
return output;
} //中间缓存的暂存结构,用于接收中间运行时需要暂存的变量数据
static class AggregateAgg implements AggregationBuffer{
Long sum;
}
@Override
public AggregationBuffer getNewAggregationBuffer() throws HiveException {
AggregateAgg result = new AggregateAgg();
reset(result);
return result;
} //刷新缓存重置暂存数据,重用jvm
@Override
public void reset(AggregationBuffer agg) throws HiveException {
AggregateAgg myAgg = (AggregateAgg)agg;
myAgg.sum = 0L;
} //对map端传入的每一条数据进行处理
@Override
public void iterate(AggregationBuffer agg, Object[] parameters) throws HiveException {
assert parameters.length == 1;
Object param = parameters[0];
if (param != null) {
AggregateAgg myAgg = (AggregateAgg)agg;
myAgg.sum ++;
}
} //返回map阶段对每一条数据处理后的数据
@Override
public Object terminatePartial(AggregationBuffer agg) throws HiveException {
AggregateAgg myAgg = (AggregateAgg)agg;
result.set(myAgg.sum);
return result;
} //在combiner和reduce时候回调用,对map输出的结果进行聚合,即每一条数据调用一下,依次将数据累加到之前的结果上
@Override
public void merge(AggregationBuffer agg, Object partial) throws HiveException {
if (partial != null) {
AggregateAgg myAgg = (AggregateAgg)agg;
myAgg.sum += PrimitiveObjectInspectorUtils.getLong(partial,input);
}
} //使用变量接收最终的结果数据,并将数据进行返回
@Override
public Object terminate(AggregationBuffer agg) throws HiveException {
AggregateAgg myAgg = (AggregateAgg)agg;
result.set(myAgg.sum);
return result;
}
}
}

hive自定义udaf函数的更多相关文章

  1. 关于CDH5.2+ 添加hive自定义UDAF函数的方法

  2. hive自定义UDTF函数叉分函数

    hive自定义UDTF函数叉分函数 1.介绍 从聚合体日志中需要拆解出来各子日志数据,然后单独插入到各日志子表中.通过表生成函数完成这一过程. 2.定义ForkLogUDTF 2.1 HiveUtil ...

  3. 048 SparkSQL自定义UDAF函数

    一:程序 1.需求 实现一个求平均值的UDAF. 这里保留Double格式化,在完成求平均值后与系统的AVG进行对比,观察正确性. 2.SparkSQLUDFDemo程序 package com.sc ...

  4. Hive自定义UDAF详解

    遇到一个Hive需求:有A.B.C三列,按A列进行聚合,求出C列聚合后的最小值和最大值各自对应的B列值.这个需求用hql和内建函数也可完成,但是比较繁琐,会解析成几个MR进行执行,如果自定义UDAF便 ...

  5. (转)Hive自定义UDAF详解

    UDAF有两种,第一种是比较简单的形式,利用抽象类UDAF和UDAFEvaluator,暂不做讨论.主要说一下第二种形式,利用接口GenericUDAFResolver2(或者抽象类AbstractG ...

  6. Spark(十三)【SparkSQL自定义UDF/UDAF函数】

    目录 一.UDF(一进一出) 二.UDAF(多近一出) spark2.X 实现方式 案例 ①继承UserDefinedAggregateFunction,实现其中的方法 ②创建函数对象,注册函数,在s ...

  7. hive自定义函数UDF UDTF UDAF

    Hive 自定义函数 UDF UDTF UDAF 1.UDF:用户定义(普通)函数,只对单行数值产生作用: UDF只能实现一进一出的操作. 定义udf 计算两个数最小值 public class Mi ...

  8. Hive 自定义函数(转)

    Hive是一种构建在Hadoop上的数据仓库,Hive把SQL查询转换为一系列在Hadoop集群中运行的MapReduce作业,是MapReduce更高层次的抽象,不用编写具体的MapReduce方法 ...

  9. Hive 自定义函数

    hive 支持自定义UDF,UDTF,UDAF函数 以自定义UDF为例: 使用一个名为evaluate的方法 package com.hive.custom; import org.apache.ha ...

随机推荐

  1. zabbix企业微信告警配置教程

    前言: zabbix企业微信告警只需要配置一次就可以使用很久了,但是发现再次配置时,总会有遗忘,很麻烦又要去重新熟悉,所以,现在记录一份详细的配置过程,方便日后再次配置. 1.zabbix_serve ...

  2. CodeForces–830A--二分,贪心

    Office Keys time limit per test 2 seconds memory limit per test 256 megabytes input standard input o ...

  3. VirtualBox更改虚拟硬盘 VDI文件空间大小的方法

    cmd执行 C:\Oracle\VirtualBox\VBoxManage.exe modifyhd

  4. C++入门经典-例9.3-类模板,简单类模板

    1:使用template关键字不但可以定义函数模板,而且可以定义类模板.类模板代表一族类,它是用来描述通用数据类型或处理方法的机制,它使类中的一些数据成员和成员函数的参数或返回值可以取任意数据类型.类 ...

  5. C++入门经典-例8.8-虚继承

    1:以前讲到从CBird类和CFish类派生子类CWaterBird时,在CWaterBird类中将存在两个CAnimal类的复制.那么如何在派生CWaterBird类时使其只存在一个CAnimal基 ...

  6. 学习 vue 需要了解的内容

    总结 vue 的目录 1. vue 基础 指令 事件 动态的属性 组件 动画 2. vue 组件通信 1. 父传子 props 2. 子传父 ref 3. 插槽 4. 组件的生命周期 3. vue 的 ...

  7. java实现几种常用排序:选择排序

    一.选择排序介绍 选择排序,顾名思义就是用逐个选择的方式来进行排序,逐个选择出数组中的最大(或最小)的元素,直到选择至最后一个元素.此时数组完成了排序. 二.选择排序原理分析 三.选择排序代码实现 / ...

  8. 微信小程序之地址联动

    这就是我们要实现的效果 <view class="consignee"> <!-- consignee 收件人 --> <text>收件人: & ...

  9. hibernate映射配置

    1. 普通字段类型 2. 主键映射 单列主键映射 多列作为主键映射 主键生成策略,查看api:   5.1.2.2.1. Various additional generators 数据库: Q:一个 ...

  10. Flask中session实现原理

    前言 flask_session是flask框架实现session功能的一个插件,用来替代flask自带的session实现机制,flask默认的session信息保存在cookie中,不够安全和灵活 ...