0.编程思想得到升华
- 当写这个框架的自定义类时,大都要继承框架的某些类
- 框架中的对象基本都是再次包装过的,基本不能之间 new 出来 ,可以考虑在对象名后面加上factory(工厂)
- 当学习新的知识时,看源码是一个非常好的方式,虽然现在还是看得有点懵逼,不过可以先理解大致流程.
- 实现类时,编写简单或自己用的函数,自需要写官方规定的方法即可。一般都是抽象方法会有提示.
0. hive中用到的对象
- Cloneable: 可克隆的 是一个接口
- ObjectInspector: obj对象鉴别器 是一个接口 继承与 Cloneable
- ObjectInspectorFactory: obj对象鉴别器工厂 是一个final class 最终类 用于生产对象
- PrimitiveObjectInspectorFactory: 基本类型 obj对象鉴别器工厂 是一个final class 最终类 与 java类型对接
- StructObjectInspector : 结构体obj对象鉴别器 是一个实现类 实现了 ObjectInspector 接口 是一个抽象类 干啥的没解析注释看不懂!!!
1.UDF
一进一出
package review.myudf;
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException;
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.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
/**
* 一般写框架的函数里面的数据类型对象 都是经过包装的 而且一般都不能 new 出来
* 实现自定义 udf
* 功能: 输入 一个基本数据类型 数据
* 输出 长度
*
* 此次编写函数 参考了 官方的 GenericUDFAbs类
*/
public class GetLengthStr extends GenericUDF {
/**
* 初始化方法
* @param arguments obj鉴别器对象数组(hive包装的)
* @return
* @throws UDFArgumentException
*/
@Override
public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {
// 1.判断参数个数
if (arguments.length != 1 || arguments == null){
// 抛出异常
throw new UDFArgumentLengthException("参数数量只能是一个");
}
// 2.判断参数类型 要求基本数据类型
if (arguments[0].getCategory() != ObjectInspector.Category.PRIMITIVE){
throw new UDFArgumentTypeException(0, "参数类型异常");
}
// 3.返回该对象数据类型
return PrimitiveObjectInspectorFactory.javaIntObjectInspector;
}
/**
* 核心业务处理逻辑
* @param arguments 这是函数传进来的参数
* @return
* @throws HiveException
*/
@Override
public Object evaluate(DeferredObject[] arguments) throws HiveException {
// 1.先获取参数
Object str = arguments[0].get();
// 2.考虑null值的特殊型 因为 hive中 有null 不是这个"null" 这是字符串
if (str == null){
return 0;
}
// 3.获取长度
int length = str.toString().length();
// 4.返回结果
return length;
}
@Override
public String getDisplayString(String[] children) {
return "";
}
}
对比源码:
public class GenericUDFAbs extends GenericUDF {
private transient PrimitiveCategory inputType;
private final DoubleWritable resultDouble = new DoubleWritable();
private final LongWritable resultLong = new LongWritable();
private final IntWritable resultInt = new IntWritable();
private final HiveDecimalWritable resultDecimal = new HiveDecimalWritable();
private transient PrimitiveObjectInspector argumentOI;
private transient Converter inputConverter;
@Override
public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {
if (arguments.length != 1) {
throw new UDFArgumentLengthException(
"ABS() requires 1 argument, got " + arguments.length);
}
if (arguments[0].getCategory() != Category.PRIMITIVE) {
throw new UDFArgumentException(
"ABS only takes primitive types, got " + arguments[0].getTypeName());
}
argumentOI = (PrimitiveObjectInspector) arguments[0];
inputType = argumentOI.getPrimitiveCategory();
ObjectInspector outputOI = null;
switch (inputType) {
case SHORT:
case BYTE:
case INT:
inputConverter = ObjectInspectorConverters.getConverter(arguments[0],
PrimitiveObjectInspectorFactory.writableIntObjectInspector);
outputOI = PrimitiveObjectInspectorFactory.writableIntObjectInspector;
break;