import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.serde2.lazy.LazyString;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.apache.hadoop.io.Text;
/**
* TODO(根据国家代码返回国家中文名)
* <p>本函数需要一个字典表文件:
* AD 安道尔共和国 Andorra
* AE 阿拉伯联合酋长国 United Arab Emirates
* AF 阿富汗 Afghanistan
* AG 安提瓜和巴布达 Antigua and Barbuda
* @author 忘尘
* @Date 2020年6月1日
*/
public class GenericUDFgetNameByCode extends GenericUDF{
// 加载静态资源
private static Map<String, String> countryMap = new HashMap<String, String>();
static {
// 加载字典表文件到内存
InputStream in = null;
// 读取字符流数据
BufferedReader reader = null;
try {
in = GenericUDFgetNameByCode.class.getClassLoader().getResourceAsStream("country");
reader = new BufferedReader(new InputStreamReader(in,"UTF-8"));
// 加载数据
String line = null;
// 截取数据
String[] strs = null;
while ((line = reader.readLine()) != null) {
// 读取到数据
strs = line.split("\t");
if (null != strs && strs.length == 3) {
countryMap.put(strs[0], strs[1]);
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if (null != reader) {
reader.close();
}
if (null != in) {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
// initialize 校验参数 & 设定返回值类型
@Override
public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {
// 进行参数的校验
// 要求:参数必须是简单的类型(primitive),并且还是简单类型中的string
// 判断函数只接收一个参数
if (null != arguments && arguments.length == 1) {
// 正常情况
// 判断是不是简单类型
if (arguments[0].getCategory() != ObjectInspector.Category.PRIMITIVE) {
throw new UDFArgumentException("该函数该函数只能接收接收简单类型的参数!");
}
// 判断是不是string类型
if (!arguments[0].getTypeName().toUpperCase().equals(PrimitiveObjectInspector.PrimitiveCategory.STRING.name())) {
throw new UDFArgumentException("该函数只能接收string类型的参数");
}
} else {
// 不正常情况
throw new UDFArgumentException("该函数需要接收参数!并且只能传递一个参数!");
}
// 设定返回类型 string
return PrimitiveObjectInspectorFactory.writableStringObjectInspector;
}
private Text outkey = new Text();
// UDF函数主要的业务逻辑
@Override
public Object evaluate(DeferredObject[] arguments) throws HiveException {
// 获取参数
LazyString p1 = (LazyString)arguments[0].get();
// 转换
String countryCode = p1.toString();
// 获取这个国家名称
String countryName = countryMap.get(countryCode);
// 判断
if (null == countryName) {
countryName = "一个不知名的小国家";
}
// hadoop中没有string 需要转为text
outkey.set(countryName);
return outkey;
}
// 调用错误的友情提示信息
@Override
public String getDisplayString(String[] children) {
return "该函数可以帮助你返回国家名称,每次传入一个国家代码";
}
}
Q.E.D.