impala 自定义函数

本博客主要包含两个自定义函数:1..统计impala 中字符串字符个数 2. 字符串过滤 

1. 需求:统计impala 中字符串字符个数

前情:与hive  不同,impala 中的length ,char_Length 统计的是字符串中的字节个数,为了实现此需求使用自定义函数

问题关键点:正确计算,速度 

关于统计字符数正确:原本以为直接通过入参的length 就行,但是结果获得到的还是字节个数,也是很迷 (注明:impala 版本为cdh5.16中的2.12)

故写法如下:
 

package com.esen.spark;
import java.io.UnsupportedEncodingException;
import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
public class Char_length extends UDF {
    /**
     * 如果返回值为 int时速度会更快 
     * @param regexstr
     * @return
     */
    public  IntWritable evaluate(Text regexstr) {
        if(regexstr!=null) {
            String str=null;
            try {
                str = new String(regexstr.getBytes(),"UTF-8");
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return  new IntWritable(str.length());
        }else {
            return null;
        }
         
        //intWritable.set(str.toCharArray().length);
    }

 

在此代码中的关键点有两个: 1,利用byte 数组创建java 中utf8 字符串 2.使用匿名byte 数组   如果不使用匿名的数组,对于1.7亿数据而言,一个简单的select count(1) from a where charleng(b)>3 的时间在13分,使用匿名的函数时间则在10s

2.需求:实现与oracle 过滤方法相同的功能

oracle 过滤方法:

  FUNCTION F_CHANGE_CHR(V_NAME VARCHAR2) RETURN VARCHAR2 IS
    RESULT VARCHAR2(200);
  BEGIN
    RESULT := REGEXP_REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(TO_SINGLE_BYTE(V_NAME),
                                                                                                                                                                      '(',
                                                                                                                                                                      ''),
                                                                                                                                                              ')',
                                                                                                                                                              ''),
                                                                                                                                                      '(',
                                                                                                                                                      ''),
                                                                                                                                              ')',
                                                                                                                                              ''),
                                                                                                                                      CHR(9),
                                                                                                                                      ''),
                                                                                                                              CHR(13),
                                                                                                                              ''),
                                                                                                                      '?',
                                                                                                                      ''),
                                                                                                              '?',
                                                                                                              ''),
                                                                                                      '《',
                                                                                                      ''),
                                                                                              '》',
                                                                                              ''),
                                                                                      '【',
                                                                                      ''),
                                                                              '】',
                                                                              ''),
                                                                      '—',
                                                                      ''),
                                                              '·',
                                                              ''),
                                                      ' ',
                                                      ''),
                                              '.',
                                              ''),
                                      ',',
                                      ''),
                              '<<',
                              ''),
                      '>>',
                      ''),'[[:punct:]]');

    RETURN RESULT;
  END;

问题难点:

在oracle 中,正则 [[:punct:]] 是过滤所有 特殊字符,但是在java 里面 \\p{Punct} 并不能达到相同效果,

impala 自定义函数最终实现:

// 实现全角转半角	

// 写法说明: 由于impala 版本较低的原因,在evaluate 的参数 变为string,返回的结果不采用Text 进行转 //换的话,在impala 的查询结果为乱码,原因位置。但是后来我在impala 2.12 版本中并不会
public static Text evaluate(Text s) throws UnsupportedEncodingException {
		if (s == null) {
			return s;
		} else {
			Text result = new Text();
			byte[] bs = s.getBytes();
			String str = new String(bs, "UTF-8");
			if (str.length() <= 0) {
				return s;
			} else {
				char[] charArray = str.toCharArray();
				//对全角字符转换的char数组遍历
				for (int i = 0; i < charArray.length; ++i) {
					int charIntValue = (int) charArray[i];
					//如果符合转换关系,将对应下标之间减掉偏移量65248;如果是空格的话,直接做转换
					if (charIntValue >= 65281 && charIntValue <= 65374) {
						charArray[i] = (char) (charIntValue - 65248);
					} else if (charIntValue == 12288) {
						charArray[i] = (char) 32;
					}
				}
				result.set(new Text(new String(charArray)));
			}
			Text newchar=change_char(result);
			return newchar;
		}
	}
// 字符过滤
    public static Text change_char(Text regexstr){
        Text returnstr=new Text();
        String targetstr=regexstr.toString();
        String target1= targetstr.
        	replaceAll("[[\\pP|\\pS]&&[^―]]","").
      		 replaceAll("\\s*|\r|\t|\n","");
      	
       returnstr.set(new Text(target1));
       return returnstr;
    }

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值