在此代码中的关键点有两个: 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),
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>
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;
}
一周热门 更多>