Hive的自定义UDTF(多列输出)

本文档详细介绍了如何继承Hive的GenericUDTF类来创建一个自定义函数,主要用于处理字符串。主要步骤包括:1)初始化方法initialize用于定义输出字段及其数据类型;2)process方法处理每行数据并使用forward写入缓冲区;3)无需在close方法中进行IO操作。示例代码展示了一个根据相似度将一行字符串转换为多行的方法。
摘要由CSDN通过智能技术生成

一、继承GenericUDTF抽象类
二、重写方法initialize()
initialize方法是针对整个任务调一次,initialize作用是定义输出字段的列名、和输出字段的数据类型,重写该方法时里面有一些知识点需要我们记

在定义输出字段(fieldNames)的数据类型(ieldOIs)时,该处定义的数据类型跟常用的Java数据类型不一致,需要格外去记。
比如string数据类型这里用的是javaStringObjectInspector;int 数据类型这里用的是javaIntObjectInspector
输出的字段名是一个集合,而不是一个字段。也就是炸裂这个方法可以输出多个列。如:hive中explode对数组炸裂时返回一个字段,explode对map数据炸裂时返回2个字段.
输出的列数据类型也是一个集合。
返回列字段名和列数据类型时,是返回的是一个工厂数据类型ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames, fieldOIs),记住就好了。

三、实现抽象方法process()
process方法是一行数据调用一次process方法,即有多少行数据就会调用多少次process方法。主要作用是对传入的每一行数据写出去多次,调用forward()将数据写入到一个缓冲区。

有2个点需要记住:

1)在initialize初始化的时候,定义输出字段的数据类型是集合,我们调用forward()将数据写入到一个缓冲区,写入缓冲区的数据也要是集合。
2)如果只定义了一个集合,每次调用forward()写数据之前,需要将集合中的数据给清空。

四、实现抽象方法close()

这里没有io流的操作所以不需要关闭。

五、自定义将一行字符串转多行代码

package com.wxn;


import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class GetSimilarity extends GenericUDTF {


    @Override
    public StructObjectInspector initialize(StructObjectInspector argOIs) throws UDFArgumentException {


        //定义输出数据的列名
        List<String> structFieldNames = new ArrayList<>();
        List<ObjectInspector> structFieldObjectInspectors = new ArrayList<>();
        structFieldNames.add("group_idx");
        structFieldObjectInspectors.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
        structFieldNames.add("cert_id");
        structFieldObjectInspectors.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);

        return ObjectInspectorFactory.getStandardStructObjectInspector(structFieldNames, structFieldObjectInspectors);


    }


    int accumulation_factor =1;

    @Override
    public void process(Object[] args) throws HiveException {
        Integer group_idx_max= Integer.valueOf(args[0].toString());

        Integer group_idx1 = Integer.valueOf(args[1].toString());

        Integer group_idx2 = Integer.valueOf(args[2].toString());

        //1.获取最新数据
        String cert_ids1 = args[3].toString();
        //2.获取上次数据
        String cert_ids2 = args[4].toString();

        //3.切分数据,得到一个数组
        String[] words1 = cert_ids1.split(",");
        String[] words2 = cert_ids2.split(",");

        List<String> collect = Arrays.stream(words1).filter(Arrays.asList(words2)::contains).collect(Collectors.toList());
        double result = (double) collect.size() / words2.length;


        if (result >= 0.8) {
            for (String word : words1) {
                try {
                    String[] dataArray = new String[2];
                    dataArray[0] = group_idx1.toString();
                    dataArray[1] = word;
                    System.out.println(dataArray[0]+":"+dataArray[1]);
                    forward(dataArray);


                } catch (Exception e) {
                    continue;
                }
            }

        }else {
            accumulation_factor=accumulation_factor++;
            group_idx_max= group_idx_max+accumulation_factor;

            for (String word : words1) {
                try {
                    String[] dataArray = new String[2];
                    dataArray[0] = String.valueOf(group_idx_max);
                    dataArray[1] = word;
                    System.out.println(dataArray[0]+":"+dataArray[1]);
                    forward(dataArray);
                } catch (Exception e) {
                    continue;
                }
            }
        }


    }

    @Override
    public void close() throws HiveException {

    }

    public String getDateTime(){
        DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDateTime now = LocalDateTime.now();
        return dtf2.format(now);
    }

    public static void main(String[] args) throws  HiveException {
        GetSimilarity getSimilarity = new GetSimilarity();

        getSimilarity.process(new Object[]{10,0,0,"a,b","a,b,c,d,e"});
    }


}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有语忆语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值