HVE 用户自定义函数UDF实例

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 "该函数可以帮助你返回国家名称,每次传入一个国家代码";
	}

}

  

posted @ 2020-06-20 11:54  我不是忘尘  阅读(226)  评论(0编辑  收藏  举报