当前位置: 首页 > news >正文

使用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位

使用Java编写Hive的UDF实现身份证号码校验及15位升级18位 背景 在数仓项目中&#xff0c;有时候会根据身份证信息做一些取数filter或者条件判断的相关运算进而获取到所需的信息。古人是用Oracle做数仓&#xff0c;理所当然是用SQL写UDF【虽然SQL写UDF给SQL用就像用鸡肉饲养肉…...

前端:分享JS中7个高频的工具函数

目录 ◆1、将数字转换为货币 ◆2、将 HTML 字符串转换为 DOM 对象 ◆3、防抖 ◆4、日期验证 ◆5、将 FormData&#xff08;表单数据&#xff09;转换为 JSON ◆6、衡量一个函数的性能 ◆7、从数组中删除重复项 JavaScript 实用函数是有用的、可重复使用的片段&#xff0…...

docker基础用法及镜像和容器的常用命令大全

1.docker 体系架构 Docker 采用了 C / S 架构&#xff0c;包括客户端和服务端。Docker 守护进程作为服务端接受来自客户端的请求&#xff0c;并处理这些请求&#xff08;创建、运行、分发容器&#xff09;。客户端和服务端既可以运行在一个机器上&#xff0c;也可通过 socket 或…...

Spring(Bean生命周期)

目录 1. 生命周期简图2. 扩展接口介绍 2.1 Aware接口2.2 BeanPostProcessor接口2.3 InitializingBean2.4 DisposableBean2.5 BeanFactoryPostProcessor接口3. spring的简化配置 3.1 项目搭建3.2 Bean的配置和值注入3.3 AOP的示例 1. 生命周期简图 2. 扩展接口介绍 2.1 Aware接…...

什么是分布式锁?几种分布式锁分别是怎么实现的?

一、什么是分布式锁&#xff1a; 1、什么是分布式锁&#xff1a; 分布式锁&#xff0c;即分布式系统中的锁。在单体应用中我们通过锁解决的是控制共享资源访问的问题&#xff0c;而分布式锁&#xff0c;就是解决了分布式系统中控制共享资源访问的问题。与单体应用不同的是&am…...

【一天一门编程语言】R 语言程序设计极简教程

R 语言程序设计极简教程 文章目录 R 语言程序设计极简教程R语言简介1.1 介绍1.2 R 语言的基础知识1.2.1 语法1.2.2 数据类型1.2.3 基本操作1.3 R 语言的高级知识1.3.1 函数1.3.2 包1.3.3 面向对象编程1.4 使用 R 语言的实践1.4.1 数据处理1.4.2 数据可视化1.4.3 数据建模1.4.3.…...

记一次顿悟的经历

2023.02.20 一次顿悟的经历 体验一次顿悟 ​ 需求&#xff1a; ​为避免接收数据时一直阻塞&#xff0c;先调用 select 在一定时间内判断是否有数据可读 如果超时&#xff0c;就报错没读到数据&#xff0c;即使返回 如果仍然在 set 里&#xff0c;就调用 recv 函数接收数据 问…...

19_FreeRTOS软件定时器

目录 软件定时器介绍 FreeRTOS软件定时器特点 软件定时器的命令队列 软件定时器的相关配置 单次定时器和周期定时器 软件定时器结构体成员 FreeRTOS软件定时器相关API函数 实验源码 软件定时器介绍 定时器描述:从指定的时刻开始,经过一个指定时间,然后触发一个超时事件…...

值得推荐!安利5款良心又好用的小众软件

电脑上的各类软件有很多&#xff0c;除了那些常见的大众化软件&#xff0c;还有很多不为人知的小众软件&#xff0c;专注于实用功能&#xff0c;简洁干净、功能强悍。今天分享5个实用的软件&#xff0c;简单实用&#xff0c;效果拉满&#xff0c;堪称工作生活必备&#xff01; …...

Enhanced ShockBurst (ESB)原文翻译

自我学习为主&#xff0c;同时也为所需要的提供一份资料 官方地址 增强型ShockBurst&#xff08;ESB&#xff09;是一种支持双向数据包通信的基本协议&#xff0c;包括数据包缓冲、数据包确认和丢失数据包的自动重传。ESB以低功耗提供无线通信&#xff0c;并且实现的代码量小且…...

软件测试之兼容性测试

对于基于计算机平台的软件&#xff0c;在测试过程中必须考虑软、硬件的兼容性&#xff0c;在设计测试用例的过程中必须考虑数据转换或转移的问题&#xff0c;应该尽力发现其可能带来的错误。不仅是基于计算机平台的软件&#xff0c;对于嵌入式软件也一样&#xff0c;在软件升级…...

笔记(一)——容器

容器分类&#xff1a;序列式容器&#xff1a;每个元素都有固定位置&#xff0c;取决于插入的时机和地点&#xff0c;和元素无关&#xff0c;如vector、deque、list、stack、queue。关联式容器&#xff1a;元素位置取决于特定的排序准则&#xff0c;和插入顺序无关&#xff0c;如…...

C++入门:命名空间

假设这样一种情况&#xff0c;当一个班上有两个名叫 Zara 的学生时&#xff0c;为了明确区分它们&#xff0c;我们在使用名字之外&#xff0c;不得不使用一些额外的信息&#xff0c;比如他们的家庭住址&#xff0c;或者他们父母的名字等等。同样的情况也出现在 C 应用程序中。例…...

操作系统(复试准备)

操作系统&#xff08;复试准备&#xff09; 第一章知识点 操作系统概述 操作系统的概念 负责协调软硬件等计算机资源的工作 为上层用户&#xff0c;应用程序提供简单易用的接口 是一种系统软件 操作系统的功能与目标 资源的管理者 处理机管理&#xff0c;存储器管理&#x…...

2023年CDGA考试模拟题库(501-600)

2023年CDGA考试模拟题库(501-600) 501.希望从数据中获取价值的组织认识到,高质量数据比低质量数据更有价值。使用劣质数据充满风险,会损害组织的声誉,导致罚款、收入损失、客户流失和负面的媒体曝光等组织基于各种业务驱动因素而着手进行数据质量管理活动,下列哪项不属于上述驱…...

NCNN+Int8+yolov5部署和量化

【GiantPandaCV引言】 还记得我在两个月前写的文章吗,关于yolov4-tiny+ncnn+int8量化的详细教程:NCNN+INT8+YOLOV4量化模型和实时推理 后来准备写yolov5+ncnn+int8量化的教程,却在yolov5的量化上遇到了麻烦,一方面是量化后速度更慢了,另一方面是精度下降严重,出现满屏都…...

springboot+vue.js协同过滤算法之智能旅游推荐系统java

目 录 第一章 绪论 3 1.1课题背景 3 1.2课题研究的目的和意义 3 1.3 研究现状 4 1.4论文所做的主要工作 4 第二章 技术介绍 5 2.1B/S结构 5 2.2MySQL 介绍 5 2.3MySQL环境配置 6 第三章 系统分析与设计 8 3.1系统说明 8 3.2系统可行性分析…...

Google Brain新提出的优化器“Lion”,效果要比Adam(W)更好

Google Brain新提出的优化器“Lion”&#xff0c;效果要比Adam(W)更好 论文地址&#xff1a;https://arxiv.org/abs/2302.06675代码地址&#xff1a;https://github.com/google/automl/blob/master/lion/lion_pytorch.py 1 简单、内存高效、运行速度更快 与 AdamW 和各种自适…...

慢雾:Discord 私信钓鱼手法分析

事件背景 5 月 16 日凌晨&#xff0c;当我在寻找家人的时候&#xff0c;从项目官网的邀请链接加入了官方的 Discord 服务器。在我加入服务器后立刻就有一个"机器人"(Captcha.bot)发来私信要我进行人机验证。这一切看起来相当的合理。我也点击了这个验证链接进行查看…...

2023-2-25 刷题情况

交换字符使得字符串相同 题目描述 有两个长度相同的字符串 s1 和 s2&#xff0c;且它们其中 只含有 字符 “x” 和 “y”&#xff0c;你需要通过「交换字符」的方式使这两个字符串相同。 每次「交换字符」的时候&#xff0c;你都可以在两个字符串中各选一个字符进行交换。 …...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

论文笔记——相干体技术在裂缝预测中的应用研究

目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术&#xff1a;基于互相关的相干体技术&#xff08;Correlation&#xff09;第二代相干体技术&#xff1a;基于相似的相干体技术&#xff08;Semblance&#xff09;基于多道相似的相干体…...

jmeter聚合报告中参数详解

sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample&#xff08;样本数&#xff09; 表示测试中发送的请求数量&#xff0c;即测试执行了多少次请求。 单位&#xff0c;以个或者次数表示。 示例&#xff1a;…...

逻辑回归暴力训练预测金融欺诈

简述 「使用逻辑回归暴力预测金融欺诈&#xff0c;并不断增加特征维度持续测试」的做法&#xff0c;体现了一种逐步建模与迭代验证的实验思路&#xff0c;在金融欺诈检测中非常有价值&#xff0c;本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...

【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验

Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...

Unity VR/MR开发-VR开发与传统3D开发的差异

视频讲解链接&#xff1a;【XR马斯维】VR/MR开发与传统3D开发的差异【UnityVR/MR开发教程--入门】_哔哩哔哩_bilibili...

DeepSeek越强,Kimi越慌?

被DeepSeek吊打的Kimi&#xff0c;还有多少人在用&#xff1f; 去年&#xff0c;月之暗面创始人杨植麟别提有多风光了。90后清华学霸&#xff0c;国产大模型六小虎之一&#xff0c;手握十几亿美金的融资。旗下的AI助手Kimi烧钱如流水&#xff0c;单月光是投流就花费2个亿。 疯…...