最后
看完上述知识点如果你深感Java基础不够扎实,或者刷题刷的不够、知识不全面
小编专门为你量身定制了一套<Java一线大厂高岗面试题解析合集:JAVA基础-中级-高级面试+SSM框架+分布式+性能调优+微服务+并发编程+网络+设计模式+数据结构与算法>
针对知识面不够,也莫慌!还有一整套的<Java核心进阶手册>,可以瞬间查漏补缺
全都是一丢一丢的收集整理纯手打出来的
更有纯手绘的各大知识体系大纲,可供梳理:Java筑基、MySQL、Redis、并发编程、Spring、分布式高性能架构知识、微服务架构知识、开源框架知识点等等的xmind手绘图~
public abstract class AbstractGenericUDAFResolver
implements GenericUDAFResolver2
{
@SuppressWarnings(“deprecation”)
@Override
public GenericUDAFEvaluator getEvaluator(GenericUDAFParameterInfo info)
throws SemanticException {
if (info.isAllColumns()) {
throw new SemanticException(
“The specified syntax for UDAF invocation is invalid.”);
}
return getEvaluator(info.getParameters());
}
@Override
public GenericUDAFEvaluator getEvaluator(TypeInfo[] info)
throws SemanticException {
throw new SemanticException(
“This UDAF does not support the deprecated getEvaluator() method.”);
}
}
- 既然源码都看了,也就没啥好纠结的了,继承父类还是实现接口都可以,您自己看着选吧,我这里选的是继承AbstractGenericUDAFResolver类;
关于UDAF的四个阶段
- 在编码前,要先了解UDAF的四个阶段,定义在GenericUDAFEvaluator的Mode枚举中:
-
COMPLETE:如果mapreduce只有map而没有reduce,就会进入这个阶段;
-
PARTIAL1:正常mapreduce的map阶段;
-
PARTIAL2:正常mapreduce的combiner阶段;
-
FINAL:正常mapreduce的reduce阶段;
每个阶段被调用的方法
-
开发UDAF时,要继承抽象类GenericUDAFEvaluator,里面有多个抽象方法,在不同的阶段,会调用到这些方法中的一个或多个;
-
下图对每个阶段调用了哪些方法说得很清楚:
- 下图对顺序执行的三个阶段和涉及方法做了详细说明:
-
以上两张图片的出处都是kent7306的文章《Hive UDAF开发详解》,地址:https://blog.csdn.net/kent7306/article/details/50110067
-
上面两幅图将抽象方法和每个阶段的关系都梳理得很清晰了,接下来咱们开始编码;
源码下载
- 如果您不想编码,可以在GitHub下载所有源码,地址和链接信息如下表所示:
| 名称 | 链接 | 备注 |
| :-- | :-- | :-- |
| 项目主页 | https://github.com/zq2599/blog_demos | 该项目在GitHub上的主页 |
| git仓库地址(https) | https://github.com/zq2599/blog_demos.git | 该项目源码的仓库地址,https协议 |
| git仓库地址(ssh) | git@github.com:zq2599/blog_demos.git | 该项目源码的仓库地址,ssh协议 |
- 这个git项目中有多个文件夹,本章的应用在hiveudf文件夹下,如下图红框所示:
UDAF开发步骤简述
开发UDAF分为以下几步:
-
新建类FieldLengthAggregationBuffer,用于保存中间结果,该类需继承AbstractAggregationBuffer;
-
新建类FieldLengthUDAFEvaluator,用于实现四个阶段中会被调用的方法,该类需继承GenericUDAFEvaluator;
-
新建类FieldLength,用于在hive中注册UDAF,里面会实例化FieldLengthUDAFEvaluator,该类需继承AbstractGenericUDAFResolver;
-
编译构建,得到jar;
-
在hive添加jar;
-
在hive注册函数;
接下来就按照上述步骤开始操作;
开发
- 打开前文新建的hiveudf工程,新建FieldLengthAggregationBuffer.java,这个类的作用是缓存中间计算结果,每次计算的结果都放入这里面,被传递给下个阶段,其成员变量value用来保存累加数据:
package com.bolingcavalry.hiveudf.udaf;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFEvaluator;
import org.apache.hadoop.hive.ql.util.JavaDataModel;
public class FieldLengthAggregationBuffer extends GenericUDAFEvaluator.AbstractAggregationBuffer {
private Integer value = 0;
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
}
public void add(int addValue) {
synchronized (value) {
value += addValue;
}
}
/**
-
合并值缓冲区大小,这里是用来保存字符串长度,因此设为4byte
-
@return
*/
@Override
public int estimate() {
return JavaDataModel.PRIMITIVES1;
}
}
- 新建FieldLengthUDAFEvaluator.java,里面是整个UDAF逻辑实现,关键代码已经添加了注释,请结合前面的图片来理解,核心思路是iterate将当前分组的字段处理完毕,merger把分散的数据合并起来,再由terminate决定当前分组计算结果:
package com.bolingcavalry.hiveudf.udaf;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFEvaluator;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
/**
-
@Description: 这里是UDAF的实际处理类
-
@author: willzhao E-mail: zq2599@gmail.com
-
@date: 2020/11/4 9:57
*/
public class FieldLengthUDAFEvaluator extends GenericUDAFEvaluator {
PrimitiveObjectInspector inputOI;
ObjectInspector outputOI;
PrimitiveObjectInspector integerOI;
/**
-
每个阶段都会被执行的方法,
-
这里面主要是把每个阶段要用到的输入输出inspector好,其他方法被调用时就能直接使用了
-
@param m
-
@param parameters
-
@return
-
@throws HiveException
*/
@Override
public ObjectInspector init(Mode m, ObjectInspector[] parameters) throws HiveException {
super.init(m, parameters);
// COMPLETE或者PARTIAL1,输入的都是数据库的原始数据
if(Mode.PARTIAL1.equals(m) || Mode.COMPLETE.equals(m)) {
inputOI = (PrimitiveObjectInspector) parameters[0];
} else {
// PARTIAL2和FINAL阶段,都是基于前一个阶段init返回值作为parameters入参
integerOI = (PrimitiveObjectInspector) parameters[0];
}
outputOI = ObjectInspectorFactory.getReflectionObjectInspector(
Integer.class,
ObjectInspectorFactory.ObjectInspectorOptions.JAVA
);
// 给下一个阶段用的,即告诉下一个阶段,自己输出数据的类型
return outputOI;
}
public AggregationBuffer getNewAggregationBuffer() throws HiveException {
return new FieldLengthAggregationBuffer();
}
/**
-
重置,将总数清理掉
-
@param agg
-
@throws HiveException
*/
public void reset(AggregationBuffer agg) throws HiveException {
((FieldLengthAggregationBuffer)agg).setValue(0);
}
/**
-
不断被调用执行的方法,最终数据都保存在agg中
-
@param agg
-
@param parameters
-
@throws HiveException
*/
public void iterate(AggregationBuffer agg, Object[] parameters) throws HiveException {
if(null==parameters || parameters.length<1) {
return;
}
Object javaObj = inputOI.getPrimitiveJavaObject(parameters[0]);
((FieldLengthAggregationBuffer)agg).add(String.valueOf(javaObj).length());
}
/**
-
group by的时候返回当前分组的最终结果
-
@param agg
-
@return
-
@throws HiveException
*/
public Object terminate(AggregationBuffer agg) throws HiveException {
return ((FieldLengthAggregationBuffer)agg).getValue();
}
/**
最后
我还通过一些渠道整理了一些大厂真实面试主要有:蚂蚁金服、拼多多、阿里云、百度、唯品会、携程、丰巢科技、乐信、软通动力、OPPO、银盛支付、中国平安等初,中级,高级Java面试题集合,附带超详细答案,希望能帮助到大家。
还有专门针对JVM、SPringBoot、SpringCloud、数据库、Linux、缓存、消息中间件、源码等相关面试题。
云、百度、唯品会、携程、丰巢科技、乐信、软通动力、OPPO、银盛支付、中国平安等初,中级,高级Java面试题集合,附带超详细答案,希望能帮助到大家。**
[外链图片转存中…(img-YvYcEw6L-1715555193695)]
还有专门针对JVM、SPringBoot、SpringCloud、数据库、Linux、缓存、消息中间件、源码等相关面试题。
[外链图片转存中…(img-oqdLBYWZ-1715555193696)]