编写Apache Hive用户自定义函数(UDF)有两个不同的接口,一个简单,另一个相对复杂:
简单API: org.apache.hadoop.hive.ql.exec.UDF--使用反射推测(参数及返回值的)类型,开发简单,不易于控制。
复杂API: org.apache.hadoop.hive.ql.udf.generic.GenericUDF --使用代码指定类型和隐式类型转换逻辑。
如果你的函数读和返回都是基础数据类型(Hadoop&Hive 基本writable类型,如Text,IntWritable,LongWriable,DoubleWritable等等),那么UDF可以胜任。
- 优点:
- 实现简单
- 支持Hive的基本类型、数组和Map
- 支持函数重载
- 缺点:
- 逻辑较为简单,只适合用于实现简单的函数
这种方式编码少,代码逻辑清晰,可以快速实现简单的UDF
但是,如果你想写一个UDF用来操作内嵌数据结构,如Map,List和Set,那么你要去熟悉GenericUDF这个API
- 优点:
- 支持任意长度、任意类型的参数
- 可以根据参数个数和类型实现不同的逻辑
- 可以实现初始化和关闭资源的逻辑(initialize、close)
- 缺点:
- 实现比继承UDF要复杂一些
与继承 UDF 相比,GenericUDF 更加灵活,可以实现更为复杂的函数
关于两者的选择
如果函数具有以下特点,优先继承 UDF 类:
- 逻辑简单,比如英文转小写函数
- 参数和返回值类型简单,都是Hive的基本类型、数组或Map
- 没有初始化或关闭资源的需求
否则考虑继承 GenericUDF 类
简单UDF API
构建一个UDF只涉及到编写一个类继承实现一个方法(evaluate),以下是示例:
class SimpleUDFExample extends UDF {
public Text evaluate(Text input) {
if(input == null) return null;
return new Text("Hello " + input.toString());
}
}
示例2:
import org.apache.hadoop.hive.ql.exec.UDF;
/**
* 继承 org.apache.hadoop.hive.ql.exec.UDF
*/
public class SimpleUDF extends UDF {
/**
* 编写一个函数,要求如下:
* 1. 函数名必须为 evaluate
* 2. 参数和返回值类型可以为:Java基本类型、Java包装类、org.apache.hadoop.io.Writable等类型、List、Map
* 3. 函数一定要有返回值,不能为 void
*/
public int evaluate(int a, int b) {
return a + b;
}
/**
* 支持函数重载
*/
public Integer evaluate(Integer a, Integer b, Integer c) {
if (a == null || b == null || c == null)
return 0;
return a + b + c;
}
}
支持的参数和返回值类型
支持 hive基本类型、数组和Map
Hive基本类型
Java可以使用Java原始类型、Java包装类或对应的Writable类
PS:对于基本类型,最好不要使用 Java原始类型,当 null 传给 Java原始类型 参数时,UDF 会报错。Java包装类还可以用于null值判断
Hive类型 | Java原始类型 | Java包装类 | hadoop.io.Writable |
---|---|---|---|
tinyint | byte | Byte | ByteWritable |
smallint | short | Short | ShortWritable |
int | int | Integer | IntWritable |
bigint | long | Long | LongWritable |
string | String | - | Text |
boolean | boolean | Boolean | BooleanWritable |
float | float | Float | FloatWritable |
double | double | Double | DoubleWritable |
数组和Map
Hive类型 | Java类型 |
---|---|
array | List |
Map<K, V> | Map<K, V& |