自定义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. 【CUDA 基础】4.2 内存管理

    title: [CUDA 基础]4.2 内存管理 categories: - CUDA - Freshman tags: - CUDA内存管理 - CUDA内存分配和释放 - CUDA内存传输 - 固 ...

  2. 微信小程序_(案例)简单中国天气网首页

    Demo:简单中国天气网首页 Page({ data:{ name:"CynicalGary", temp:"4", low:"-1°C", ...

  3. Android学习_数据持久化

    数据持久化:将内存中的瞬时数据存储到设备中 1. 文件存储 存储一些简单的文本数据或二进制数据. 核心:Context类提供的openFileOutput()和openFileInput()方法,然后 ...

  4. JavaScript数字计算精度丢失的问题和解决方案

    一.JS数字精度丢失的一些典型问题 1. 两个简单的浮点数相加:0.1 + 0.2 != 0.3 // true,下图是firebug的控制台截图: 看看java的计算结果:是不是让你很不能接受 再来 ...

  5. RESTful API是什么?

    1. REST 是Repersentational State Transfer的缩写 翻译为"表述性状态传递",那么什么是表述性状态传递呢?为了理解这个词语,我们从"R ...

  6. tomcat建立双向https安全连接

    参考:http://www.hangge.com/blog/cache/detail_992.htmltomcat连接器的框架是coyote,有关信息参考:http://blog.csdn.net/w ...

  7. SRS之RTMP的TCP线程(即监听线程)

    本文分析的是 SRS 针对 rtmp 的端口建立的 tcp 线程.具体建立过程: SRS之监听端口的管理:RTMP RTMP 的 TCP 线程中各个类之间 handler 的关系图 1. RTMP之T ...

  8. SQLSTATE[HY000] [2002] Connection refused

    //域名绑定到模块 '__domain__' => [ 'admin' => 'admin', 'post' => 'api', 'user' => 'index', 'www ...

  9. k8s简单介绍

    k8s是什么? 它是用来解决容器部署,调度,伸缩等基础的功能的软件 k8s的优点? 易学:轻量级,简单,容易理解 便携:支持公有云,私有云,混合云,以及多种云平台 可拓展:模块化,可插拔,支持钩子,可 ...

  10. koa 项目实战(五)全球公用头像的使用

    1.安装模块 npm install gravatar --save 2.使用 根目录/routes/api/users.js const gravatar = require('gravatar') ...