udf是对hive上的每行(单行)数据操作,现在我要实现对hive上的一列数据操作,udf函数已经满足不了我的要求了,使用udaf对hive的一列求最大值;
代码如下:
1 package com; 2 3 import org.apache.hadoop.hive.ql.exec.UDAF; 4 import org.apache.hadoop.hive.ql.exec.UDAFEvaluator; 5 import org.apache.hadoop.io.FloatWritable; 6 import org.apache.commons.math3.stat.descriptive.rank.Max; 7 8 public class MaxFloat extends UDAF{ 9 public Object Max; 10 public static class MaxiNumberIntUDAFEvaluator implements UDAFEvaluator{ 11 //最终结果 12 private FloatWritable result; 13 //负责初始化计算函数并设置它的内部状态,result是存放最终结果的 14 public void init() { 15 result=null; 16 } 17 //每次对一个新值进行聚集计算都会调用iterate方法 18 public boolean iterate(FloatWritable value) 19 { 20 if(value==null) 21 return false; 22 if(result==null) 23 result=new FloatWritable(value.get()); 24 else{ 25 Max max = new Max(); 26 double[] values = new double[2]; 27 values[0] = result.get(); 28 values[1] = value.get(); 29 result.set((float) max.evaluate(values)); 30 // result.set(Math.max(result.get(), value.get())); 31 } 32 return true; 33 } 34 //Hive需要部分聚集结果的时候会调用该方法 35 //会返回一个封装了聚集计算当前状态的对象 36 public FloatWritable terminatePartial() 37 { 38 return result; 39 } 40 //合并两个部分聚集值会调用这个方法 41 public boolean merge(FloatWritable other) 42 { 43 return iterate(other); 44 } 45 //Hive需要最终聚集结果时候会调用该方法 46 public FloatWritable terminate() 47 { 48 return result; 49 } 50 } 51 }
按照这种格式写各种函数;
打成jar包(打jar包的步骤我之前的博客里有详细描述)
将jar包和测试数据导入linux
登入hive,执行以下操作:
add jar /home/data_service/ysf/jar_test/MaxFloat.jar;
create temporary function maxf as 'com.MaxFloat';
set hive.limit.optimize.enable=true;
set hive.fetch.task.conversion=more;
select maxf(num) from dim_number_test_ysf4;
结果如下:
源数据为:
0.33
1.33
0.27333
0.3
0.501
0.444
0.44
0.34496
0.33
0.3
0.292
0.667
总结:一开始,我以为udf可以,后面问其他同事,才知道原来udf只对hive单行数据进行处理,立马五脸懵逼,各种百度,没想到真找到了,感谢度娘。