hive UDF自定义函数 map处理

创建工程

新建JAVA或者maven项目,并添加 hive-exec-2.1.0.jar 和hadoop-common-2.7.3.jar
 hive-exec-2.1.0.jar 在HIVE安装目录的lib目录下,从安装目录直接下载放到工程中即可
 hadoop-common-2.7.3.jar在hadoop的安装目录下的\share\hadoop\common

编写自定义UDF函数

当写hive UDF时,有两个选择:一是继承 UDF类,二是继承抽象类GenericUDF。这两种实现不同之处 是:GenericUDF 可以处理复杂类型参数,并且继承GenericUDF更加有效率,因为UDF class 需要HIve使用反射的方式去实现。
处理map类型的数据,是复杂类型因此继承GenericUDF。

简单说明:

// 这个类似于简单API的evaluat方法,它可以读取输入数据和返回结果  
abstract Object evaluate(GenericUDF.DeferredObject[] arguments);  

// 该方法无关紧要,我们可以返回任何东西,但应当是描述该方法的字符串  
abstract String getDisplayString(String[] children);  

// 只调用一次,在任何evaluate()调用之前,你可以接收到一个可以表示函数输入参数类型的object inspectors数组  
// 这是你用来验证该函数是否接收正确的参数类型和参数个数的地方  
abstract ObjectInspector initialize(ObjectInspector[] arguments); 

实现map数据排序

import java.util.ArrayList;  
import java.util.Collections;  
import java.util.Comparator;  
import java.util.HashMap;  
import java.util.LinkedHashMap;  
import java.util.List;  
import java.util.Map;  
import java.util.Map.Entry;  

import org.apache.hadoop.hive.ql.exec.UDFArgumentException;  
import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException;  
import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException;  
import org.apache.hadoop.hive.ql.metadata.HiveException;  
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;  
import org.apache.hadoop.hive.serde2.objectinspector.MapObjectInspector;  
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;  
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;  
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector.Category;  
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;  
import org.apache.hadoop.io.Text;  

/** 
 * Sort a map 
 * the function simple:sort_map(map,'key','desc'),返回map(string,string) 
 * @author Irwin 
 * 
 */  
public class SortMapTest extends GenericUDF {  

    private MapObjectInspector mapOI;  
    private final Map<Text, Text> sortMap = new LinkedHashMap<Text, Text>();  

    private ArrayList<Object> keyList = new ArrayList<Object>();  
    private ArrayList<Object> valueList = new ArrayList<Object>();  

    @Override  
    public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {  
    // 检查是否接收到正确的参数类型  
        if (arguments.length != 3) {  
              throw new UDFArgumentLengthException("The function SORT_MAP only accepts 3 argument. simple: sort_map(map,'key','desc')");  
            } else if (!(arguments[0] instanceof MapObjectInspector) || !(arguments[1] instanceof ObjectInspector) || !(arguments[2] instanceof ObjectInspector)) {  
              throw new UDFArgumentTypeException(0, "\""  
                  + Category.MAP.toString().toLowerCase()  
                  + "\" is expected at function SORT_MAP, " + "but \""  
                  + arguments[0].getTypeName() + " or " + arguments[1].getTypeName() + " or " +  arguments[2].getTypeName() + "\" is found");  
            }  

            mapOI = (MapObjectInspector) arguments[0];  
            //定义返回类型参数
            return ObjectInspectorFactory.getStandardMapObjectInspector(  
                    PrimitiveObjectInspectorFactory.writableStringObjectInspector,   
                    PrimitiveObjectInspectorFactory.writableStringObjectInspector);  
    }  

    @Override  
    public Object evaluate(DeferredObject[] arguments) throws HiveException {  
        sortMap.clear();  
        keyList.clear();  
        valueList.clear();  
        Object mapObj = arguments[0].get();  
        String key_valueObj = ((Text)arguments[1].get()).toString();  
        String orderObj =  ((Text)arguments[2].get()).toString();  
        keyList.addAll(mapOI.getMap(mapObj).keySet());  
        valueList.addAll(mapOI.getMap(mapObj).values());  

        Map<Text,Text> inputMap = new HashMap<Text, Text>();  
        //put keys and values  
        for (int i = 0; i < keyList.size(); i++) {  
            inputMap.put(new Text(keyList.get(i).toString()), new Text(valueList.get(i).toString()));  
        }  
        if (key_valueObj.equals("key")) {  
            sortMap.putAll(sortMayByKey(inputMap, orderObj)); 

            return sortMap;  
        }else {  
            sortMap.putAll(sortMapByValue(inputMap, orderObj));  
            return sortMap;  
        }  
    }  

    @Override  
    public String getDisplayString(String[] children) {  
        return "map(" + children[0] + ")";  
    }  

    public static Map<Text, Text> sortMapByValue(Map<Text, Text> map, final String order) {  
        Map<Text, Text> sortMap = new LinkedHashMap<Text, Text>();  
        List<Map.Entry<Text, Text>> list_Data = new ArrayList<Map.Entry<Text, Text>>(map.entrySet());  
        // 通过Collections.sort(List I,Comparator c)方法进行排序  
        Collections.sort(list_Data,  
                new Comparator<Map.Entry<Text, Text>>() {  

                    @Override  
                    public int compare(Entry<Text, Text> o1, Entry<Text, Text> o2) {  
                        if (order.equals("asc")) {  
                            return o1.toString().compareTo(o2.toString());  
                        } else {  
                            return o2.toString().compareTo(o1.toString());  
                        }  
                    }  
                });  
        // put the sorted map  
        for (Entry<Text, Text> entry : list_Data) {  
            sortMap.put(entry.getKey(), entry.getValue());  
        }  
        return sortMap;  
    }  

    public static Map<Text, Text> sortMayByKey(Map<Text, Text> map, final String order) {  
        Map<Text, Text> sortMap = new LinkedHashMap<Text, Text>();  
        List<Text> arrayList = new ArrayList<Text>(map.keySet());    
        Collections.sort(arrayList, new Comparator<Text>() {  
            @Override  
            public int compare(Text o1, Text o2) {  
                if (order.equals("asc")) {  
                    return o1.toString().compareTo(o2.toString());  
                }else {  
                    return o2.toString().compareTo(o1.toString());  
                }  
            }  
        });  
        //将排序好的key返回  
        for (Text key : arrayList) {  
            sortMap.put(key, map.get(key));  
        }  
        return sortMap;  
    }  
}  

打成jar包

如果想在Hive中使用UDF,那么需要将Java代码进行编译,然后将编译后的UDF二进制类文件打包成一个JAR文件。如下步骤:
1.右键项目,选择Export;
2.选择导出格式为JAR file格式
3.点击Next,选择要导出的项目,以及填写导出的目录:
这里写图片描述
4.点击Finish完成

hive中操作

1.将jar包上传到服务器上
2.在hive中

add jar /home/hdfs/hadoop-SortMapLabelTest.jar;
create temporary function sort_map as '程序的包名.类名';
select sort_map(usageinfo,'key','asc') from tmp_usage_map_h

 需要注意的是,JAR文件路径是不需要用引号括起来的,同时,到目前为止这个路径需要是当前文件系统的全路经。Hive不仅仅将这个JAR文件加入到classpath下,同时还将其加入到分布式缓存中,这样整个集群的机器都是可以获得该JAR文件的。

 需要注意的是,CREATE FUNCTION语句中的TEMPORARY这个关键字。当前会话中声明的函数只会在当前会话中有效。因此用户需要在每个会话中都增加JAR然后创建函数。不过,如果用户需要频繁地使用同一个JAR文件和函数的话,那么可以将相关语句增加到$HOME/.hiverc文件中去。

参考:一些网址

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值