日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

使用Java编写Hive的UDF实现身份证号码校验及15位升级18位

發布時間:2024/3/24 java 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用Java编写Hive的UDF实现身份证号码校验及15位升级18位 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

使用Java編寫Hive的UDF實現身份證號碼校驗及15位升級18位

背景

在數倉項目中,有時候會根據身份證信息做一些取數filter或者條件判斷的相關運算進而獲取到所需的信息。古人是用Oracle做數倉,理所當然是用SQL寫UDF【雖然SQL寫UDF給SQL用就像用雞肉飼養肉雞一樣,令筆者感嘆Oracle的神奇】。自從Oracle數據庫開發崗位被取締后,SQL Boy們就搖身一變,成為還是只會寫Hive SQL腳本的大數據開發攻城獅。本來SQL Boy們力推“原則上不允許寫Java和Scala,只允許寫SQL”,但是純SQL的方式寫出來,case when里套case when,套了好幾層,還沒有寫完,就已經有幾百行了。由于HQL任務可能多次用到這個功能,會導致凡是用到這種判斷算法的HQL腳本最終能有幾千行、上w行,不忍直視。所以最迂腐的SQL Boy也終于還是想明白了原則上不允許代表著實際上可以這么做。筆者就寫了這個UDF來大幅減少HQL任務的篇幅,提升美觀性。日后更多的SQL Boy也可以直接套用這個方法提高開發效率。

原理

參考:https://lizhiyong.blog.csdn.net/article/details/126186377

眾所周知,Hive不可以像Oracle那樣用SQL寫UDF,所以需要Java寫,并且打Jar包注冊運行。底層原理參照之前的這篇。簡單起見,就不繼承GenericUDF了,而是繼承UDF。

具體的規則,需要參考國標:GB11643-1999。老的 GB11643-1989 已經淘汰了,這也是為神馬要有15位升級18位的功能。國標中已經給出了具體的系數和校驗位的算法,照貓畫虎即可。

算法

先去除臟數據,如果滿足15位長,就升級18位。如果是18位,就算出校驗碼判斷是否和數據的校驗碼一致。為了讓判斷更嚴謹,當然還需要添加一些判斷,例如上上世紀【1900年之前】出生的人一定不會用自己的身份證號買車了。。。這些都是業務代碼,日后可以根據實際情況再做修正,比純SQL方式的可維護性好太多了。

Java實現

pom

<properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><hive-exec.version>3.1.2</hive-exec.version><encoding>UTF-8</encoding></properties><dependencies><dependency><groupId>org.apache.hive</groupId><artifactId>hive-exec</artifactId><version>${hive-exec.version}</version><exclusions><exclusion><groupId>org.glassfish</groupId><artifactId>javax.el</artifactId></exclusion></exclusions></dependency></dependencies>

只需要這個 hive-exec 依賴即可。筆者當前版本的Apache Hive有依賴沖突,故手動排除了glassfish。

Java類

package com.zhiyong;import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.hive.ql.exec.UDF;import java.text.SimpleDateFormat; import java.util.Date;/*** @program: zhiyong_study* @description: HiveUDF用于檢測是否為身份證號* @author: zhiyong* @create: 2023-02-23 21:27**/ public class IdCardCheck {//順便用main方法做單元測試public static void main(String[] args) {String input1 = "142222190001011111";String input2 = "abCd1900ya101111x";String input3 = "#s12311111 11";String input4 = "###############";String input5 = "########### @";String input6 = "111112222233333";String input7 = "110 10 03x";String input8 = "11 946 9120 3";String input9 = "11 21951 2311 X";Udf_zhiyong_id_check udf_zhiyong_id_check = new Udf_zhiyong_id_check();System.out.println("result1 = " + udf_zhiyong_id_check.evauate(input1));System.out.println("result2 = " + udf_zhiyong_id_check.evauate(input2));System.out.println("result3 = " + udf_zhiyong_id_check.evauate(input3));System.out.println("result4 = " + udf_zhiyong_id_check.evauate(input4));System.out.println("result5 = " + udf_zhiyong_id_check.evauate(input5));System.out.println("result6 = " + udf_zhiyong_id_check.evauate(input6));System.out.println("result7 = " + udf_zhiyong_id_check.evauate(input7));System.out.println("result8 = " + udf_zhiyong_id_check.evauate(input8));System.out.println("result9 = " + udf_zhiyong_id_check.evauate(input9));} }/*** UDF用于判斷是否為身份證號碼,18位則返回,15位則升級18位,否則返回空串*/ class Udf_zhiyong_id_check extends UDF {public String evauate(String input) {String result = "";if (StringUtils.isEmpty(input)) {return "";}result = input.replaceAll("x", "X") //x->X.replaceAll("([a-z]+)", "") //去除a-z.replaceAll("([A-W]+)", "") //去除A-W.replaceAll("([Y-Z]+)", "") //去除Y-Z.replaceAll("\\s*", "") //去除所有空格;int length = result.length();if (!(15 == length || 18 == length)) {//必須是15位或者18位return "";}for (int i = 0; i < length; i++) {try {int parseInt = Integer.parseInt(String.valueOf(result.charAt(i)));} catch (NumberFormatException e) {if (!(i == 17 && String.valueOf(result.charAt(i)).equals("X"))) {return "";}}}//+一些判斷讓UDF更嚴謹//=====================================START================================Boolean flg = false;int[] provinceCode = {11, 12, 13, 14, 15, //華北21, 22, 23, //東北31, 32, 33, 34, 35, 36, 37, //華東41, 42, 43, //華中44, 45, 46, //華南50, 51, 52, 53, 54, //西南61, 62, 63, 64, 65, //西北81, 82, 83 //港澳臺};for (int i = 0; i < provinceCode.length; i++) {if (provinceCode[i] == Integer.parseInt(result.substring(0, 2))) {flg = true;}}if (!flg) {return "";}int year = 0;int month = 0;int day = 0;if (15 == length) {year = 1900 + Integer.parseInt(result.substring(6, 8));month = Integer.parseInt(result.substring(8, 10));day = Integer.parseInt(result.substring(10, 12));} else {year = Integer.parseInt(result.substring(6, 10));month = Integer.parseInt(result.substring(10, 12));day = Integer.parseInt(result.substring(12, 14));}if (year * 1000 + month * 100 + day >Integer.parseInt(new SimpleDateFormat("yyyyMMdd").format(new Date()))|| year < 1900) {return "";}if (month > 12 || month < 1) {return "";}if (day > 31 || day < 1) {return "";}if (day == 31 && (month == 4 || month == 6 || month == 9 || month == 11)) {return "";}if (month == 2 && day > 28) {if (day > 29) {return "";}//29號只存在于閏年if (!(year % 100 == 0 || (year % 4 == 0 && year % 100 != 0))) {return "";}}//==============================END============================int[] tmp1 = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}; //存儲系數String[] tmp2 = {"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"}; //存儲尾數int sum = 0;if (15 == length) {//身份證15位->18位String str_17 = result.substring(0, 6) + "19" + result.substring(6, 15);for (int i = 0; i < str_17.length(); i++) {//逐位相乘及sumsum += Integer.parseInt(String.valueOf(str_17.charAt(i))) * tmp1[i];}for (int i = 0; i < tmp2.length; i++) {if (i == sum % 11) {return str_17 + tmp2[i];}}}//18位的需要校驗尾數for (int i = 0; i < length - 1; i++) {sum += Integer.parseInt(String.valueOf(result.charAt(i))) * tmp1[i];}for (int i = 0; i < tmp2.length; i++) {if (i == sum % 11) {if (!(tmp2[i].equals(String.valueOf(result.charAt(17))))) {return "";}}}return result;}}

大數據行業,業務算法不值錢,值錢的是數據。。。筆者把sit驗證用的數據脫敏了。。。讀者可以自己搞一些驗證。

結果

當使用正確的數據時,可以返回值。如果有多余的空格,也可以去除掉并且返回正確的值。如果是錯誤的數據,就返回空串。

打Jar包上傳DataPhin和上傳到Apache Hive操作略有不同,底層實現是一致的,如果是別的平臺也是類似的做法,要觸類旁通!!!

總結

大數據開發中,如果處理的是結構化的表,用功能極其簡陋的SQL并沒有什么問題,反倒腳本短小易于閱讀還有開發運維容易的優勢。涉及到略微不那么簡單的遞歸迭代、循環遍歷、多路分支,純SQL硬寫也寫得出來并且語法沒問題的話也可以湊合著跑起來。但是遇到處理的是文件、流、或者每一條數據的字段個數不一樣多的log,數據不再是結構化的表時,SQL就完全沒有用武之地。雖然不如Scala那么強大,但是Java做這些事情還是比SQL強很多。原則是死的,人是活的,要與時俱進學會變通!!!

總結

大數據開發中,如果處理的是結構化的表,用功能極其簡陋的SQL并沒有什么問題,反倒腳本短小易于閱讀還有開發運維容易的優勢。涉及到略微不那么簡單的遞歸迭代、循環遍歷、多路分支,純SQL硬寫也寫得出來并且語法沒問題的話也可以湊合著跑起來。但是遇到處理的是文件、流、或者每一條數據的字段個數不一樣多的log,數據不再是結構化的表時,SQL就完全沒有用武之地。雖然不如Scala那么強大,但是Java做這些事情還是比SQL強很多。原則是死的,人是活的,要與時俱進學會變通!!!

轉載請注明出處:https://lizhiyong.blog.csdn.net/article/details/129220107

總結

以上是生活随笔為你收集整理的使用Java编写Hive的UDF实现身份证号码校验及15位升级18位的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。