实现方法:java
1. 继承UDF类
2. 重写evaluate方法apache
/** * @function 自定义UDF统计最小值 * @author John * */ public class Min extends UDF { public Double evaluate(Double a, Double b) { if (a == null) a = 0.0; if (b == null) b = 0.0; if (a >= b) { return b; } else { return a; } } }
实现方法:
一、用户的UDAF必须继承了org.apache.hadoop.hive.ql.exec.UDAF;
二、用户的UDAF必须包含至少一个实现了org.apache.hadoop.hive.ql.exec的静态类,诸如实现了 UDAFEvaluator
三、一个计算函数必须实现的5个方法的具体含义以下:
init():主要是负责初始化计算函数而且重设其内部状态,通常就是重设其内部字段。通常在静态类中定义一个内部字段来存放最终的结果。
iterate():每一次对一个新值进行汇集计算时候都会调用该方法,计算函数会根据汇集计算结果更新内部状态。当输 入值合法或者正确计算了,则 就返回true。
terminatePartial():Hive须要部分汇集结果的时候会调用该方法,必需要返回一个封装了汇集计算当前状态的对象。
merge():Hive进行合并一个部分汇集和另外一个部分汇集的时候会调用该方法。
terminate():Hive最终汇集结果的时候就会调用该方法。计算函数须要把状态做为一个值返回给用户。
四、部分汇集结果的数据类型和最终结果的数据类型能够不一样。 数组
package hive.udaf; import org.apache.hadoop.hive.ql.exec.UDAF; import org.apache.hadoop.hive.ql.exec.UDAFEvaluator; public class Avg extends UDAF { public static class AvgState { private long mCount; private double mSum; } public static class AvgEvaluator implements UDAFEvaluator { AvgState state; public AvgEvaluator() { super(); state = new AvgState(); init(); } /** * init函数相似于构造函数,用于UDAF的初始化 */ public void init() { state.mSum = 0; state.mCount = 0; } /** * iterate接收传入的参数,并进行内部的轮转。其返回类型为boolean * * @param o * @return */ public boolean iterate(Double o) { if (o != null) { state.mSum += o; state.mCount++; } return true; } /** * terminatePartial无参数,其为iterate函数遍历结束后,返回轮转数据, * terminatePartial相似于hadoop的Combiner * * @return */ public AvgState terminatePartial() { // combiner return state.mCount == 0 ? null : state; } /** * merge接收terminatePartial的返回结果,进行数据merge操做,其返回类型为boolean * * @param o * @return */ public boolean merge(AvgState avgState) { if (avgState != null) { state.mCount += avgState.mCount; state.mSum += avgState.mSum; } return true; } /** * terminate返回最终的汇集函数结果 * * @return */ public Double terminate() { return state.mCount == 0 ? null : Double.valueOf(state.mSum / state.mCount); } } }
实现方法:ide
1. 继承org.apache.hadoop.hive.ql.udf.generic.GenericUDTF
2.initialize():UDTF首先会调用initialize方法,此方法返回UDTF的返回行的信息(返回个数,类型)
3.process:初始化完成后,会调用process方法,真正的处理过程在process函数中,在process中,每一次forward() 调用产生一行;若是产生多列 能够将多个列的值放在一个数组中,而后将该数组传入到forward()函数
4.最后close()方法调用,对须要清理的方法进行清理函数
import java.util.ArrayList; import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF; import org.apache.hadoop.hive.ql.exec.UDFArgumentException; import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException; import org.apache.hadoop.hive.ql.metadata.HiveException; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory; import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; //切分”key:value;key:value;”这种字符串,返回结果为key, value两个字段 public class ExplodeMap extends GenericUDTF{ @Override public void close() throws HiveException { // TODO Auto-generated method stub } @Override public StructObjectInspector initialize(ObjectInspector[] args) throws UDFArgumentException { if (args.length != 1) { throw new UDFArgumentLengthException("ExplodeMap takes only one argument"); } if (args[0].getCategory() != ObjectInspector.Category.PRIMITIVE) { throw new UDFArgumentException("ExplodeMap takes string as a parameter"); } ArrayList<String> fieldNames = new ArrayList<String>(); ArrayList<ObjectInspector> fieldOIs = new ArrayList<ObjectInspector>(); fieldNames.add("col1"); fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector); fieldNames.add("col2"); fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector); return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames,fieldOIs); } @Override public void process(Object[] args) throws HiveException { String input = args[0].toString(); String[] test = input.split(";"); for(int i=0; i<test.length; i++) { try { String[] result = test[i].split(":"); forward(result); } catch (Exception e) { continue; } } } }
UDTF有两种使用方法,一种直接放到select后面,一种和lateral view一块儿使用oop
1:直接select中使用lua
select explode_map(properties) as (col1,col2) from src;
不能够添加其余字段使用spa
select a, explode_map(properties) as (col1,col2) from src
不能够嵌套调用code
select explode_map(explode_map(properties)) from src
不能够和group by/cluster by/distribute by/sort by一块儿使用对象
select explode_map(properties) as (col1,col2) from src group by col1, col2
2:和lateral view一块儿使用
select src.id, mytable.col1, mytable.col2 from src lateral view explode_map(properties) mytable as col1, col2;