JQuick Transform Function
JQuick Transform Function
Section titled “JQuick Transform Function”jquick-transform-function 是 JQuick 生态的通用数据转换函数库。它提供一个统一的函数注册中心 JQuickMethodInvocationManager,把字段类型转换、码值翻译、脱敏校验、条件判断等逻辑收敛为「按名称调用的函数」,业务代码里不必再反复编写同类转换分支。
库为纯 Java 实现,JDK 8+,无重型第三方依赖;函数通过 JDK 原生 SPI(java.util.ServiceLoader)发现与加载,不依赖 Spring 容器,普通 Java 工程、Spring / Spring Boot 工程均可直接引入,已在达梦(DM)、KingbaseES 等国产数据库配套场景中使用。
Maven 坐标:io.github.paohaijiao:jquick-transform-function:1.4.0(Maven Central 最新发布版)。
✨ 核心特性
Section titled “✨ 核心特性”- 259 个内置函数:字符串、数学、日期时间、条件、类型转换、业务(身份证 / 手机号 / 银行卡)、集合、数组、位运算、布尔、随机数、JSON、加解密(AES/RSA/ECC)、几何与向量、扩展转换、码值翻译共 16 大类。
- 原生 Java SPI 扩展:自定义转换函数实现接口并在
META-INF/services/注册即可,插件式扩展,不改源码。 - 可覆盖内置函数:注册同名函数(或更高优先级)即可替换内置实现。
- 统一调用入口:线程安全单例
JQuickMethodInvocationManager,按名称调用任意函数。 - Lambda 一行注册:简单函数可用 Lambda 直接注册,不必新建类文件。
- 零侵入、轻量级:JDK 8+,不绑定任何框架,遗留系统可平滑引入。
- 生态直接复用:jquick-sql、jquick-excel 均已直接依赖本组件,函数可在 SQL 与 Excel 导入导出中直接使用。
📦 Maven 依赖
Section titled “📦 Maven 依赖”Maven:
<dependency> <groupId>io.github.paohaijiao</groupId> <artifactId>jquick-transform-function</artifactId> <version>1.4.0</version></dependency>Gradle:
implementation 'io.github.paohaijiao:jquick-transform-function:1.4.0'🚀 快速上手
Section titled “🚀 快速上手”以下示例可直接编译运行,无需任何初始化代码——首次调用时注册中心自动通过 SPI 加载全部内置函数。
package demo;
import com.github.paohaijiao.function.manager.JQuickMethodInvocationManager;
/** * jquick-transform-function 最简示例 */public class TransformQuickStart {
public static void main(String[] args) { // 获取线程安全的注册中心单例 JQuickMethodInvocationManager manager = JQuickMethodInvocationManager.getInstance();
// 字符串函数:转大写 Object upper = manager.invoke("toUpper", "hello"); // HELLO
// 数学函数:多参数求和 Object sum = manager.invoke("add", 10, 20, 30); // 30.0
// 字符串截取 Object sub = manager.invoke("substring", "hello world", 0, 5); // hello
// 业务函数:手机号脱敏 Object masked = manager.invoke("phoneMask", "13812345678"); // 138****5678
System.out.println(upper + " / " + sum + " / " + sub + " / " + masked);
// 运行期打印全部已注册函数(259 个),便于排查函数名 manager.printRegisteredMethods(); }}内置转换函数
Section titled “内置转换函数”以下每个函数都给出可直接复制的调用 demo。代码块中的 manager 即快速上手中获取的 JQuickMethodInvocationManager 单例,行尾注释为调用结果或返回内容。
字符串处理(64 个)
Section titled “字符串处理(64 个)”基础判断与比较:
// 空串 / 空白判断manager.invoke("isBlank", " "); // truemanager.invoke("isString", 1); // falsemanager.invoke("length", "hello"); // 5
// 字符构成判断manager.invoke("isAlpha", "abc"); // truemanager.invoke("isAlphaNumeric", "ab1"); // truemanager.invoke("isNumeric", "123"); // true
// 包含与查找manager.invoke("contains", "hello", "ell"); // truemanager.invoke("indexOf", "hello", "l"); // 2manager.invoke("indexOf", "hello", "l", 3); // 3(从下标 3 开始找)manager.invoke("matches", "abc123", "[a-z]+\\d+"); // true
// 比较manager.invoke("compareTo", "abc", "abd"); // -1manager.invoke("compareTo", "ABC", "abc", true); // 0(忽略大小写)manager.invoke("equalsIgnoreCase", "AbC", "aBc"); // truemanager.invoke("equalsAny", "a", "b", "a"); // true
// 编辑距离(Levenshtein):最少单字符增删改次数manager.invoke("levenshtein", "kitten", "sitting"); // 3截取、填充与掩码:
// 拼接manager.invoke("concat", "a", "b", "c"); // abc
// 截取manager.invoke("left", "hello", 2); // hemanager.invoke("right", "hello", 2); // lomanager.invoke("mid", "hello", 1, 3); // ellmanager.invoke("substring", "hello world", 0, 5); // hellomanager.invoke("substringBefore", "a,b,c", ","); // amanager.invoke("substringAfter", "a,b,c", ","); // b,cmanager.invoke("substringBetween", "a[b]c", "[", "]"); // b
// 填充对齐manager.invoke("leftPad", "7", 3, "0"); // 007manager.invoke("rightPad", "ab", 4, "."); // ab..manager.invoke("centerPad", "ab", 6); // " ab "
// 掩码:mask 下标区间为 [start, end)manager.invoke("mask", "13812345678", 3, 7); // 138****5678
// 缩写:maxWidth 包含省略号本身manager.invoke("abbreviate", "abcdefg", 6); // abc...替换、转换与聚合:
// 重复manager.invoke("repeat", "ab", 2, "-"); // ab-abmanager.invoke("repeatChar", "-", 3); // ---
// 替换manager.invoke("replace", "hello world", "world", "java"); // hello javamanager.invoke("replaceAll", "a1b2c3", "\\d", "#"); // a#b#c#
// 反转与大小写manager.invoke("reverse", "abc"); // cbamanager.invoke("swapCase", "Hello"); // hELLOmanager.invoke("toUpper", "hello"); // HELLOmanager.invoke("toLower", "HELLO"); // hellomanager.invoke("trim", " hi "); // himanager.invoke("capitalize", "hello"); // Hellomanager.invoke("uncapitalize", "Hello"); // hello
// 命名风格转换manager.invoke("toCamelCase", "user_name"); // userNamemanager.invoke("toSnakeCase", "userName"); // user_namemanager.invoke("toString", 123); // 123
// 去除manager.invoke("removeStart", "userName", "user"); // Namemanager.invoke("removeEnd", "demo.txt", ".txt"); // demomanager.invoke("removeWhitespace", " a b\tc "); // abcmanager.invoke("removeDuplicates", "aabbcc"); // abc(去除相邻重复)manager.invoke("uniqueChars", "abac"); // abc(按首次出现保留唯一)
// 分词与统计manager.invoke("wordCount", "hello world"); // 2manager.invoke("tokenize", "a,b;c", ",;"); // [a, b, c]manager.invoke("split", "a,b,c", ","); // [a, b, c]manager.invoke("splitByLength", "abcdef", 2); // [ab, cd, ef]manager.invoke("countChar", "banana", "a"); // 3manager.invoke("countMatches", "aaa", "a"); // 3
// 聚合连接:第一个参数为分隔符manager.invoke("groupConcat", ",", "a", "b", "c"); // a,b,cmanager.invoke("stringAgg", "-", "a", "b", "c"); // a-b-c
// 格式化:底层为 String.formatmanager.invoke("format", "%s=%d", "age", 18); // age=18
// 相似度(返回 0~100 的相似度数值)manager.invoke("similarity", "abc", "abd");
// 转义与编解码manager.invoke("escapeHtml", "<a>"); // <a>manager.invoke("unescapeHtml", "<"); // <manager.invoke("escapeRegex", "a.b"); // a\.bmanager.invoke("encodeUrl", "a b&c"); // a%20%26cmanager.invoke("decodeUrl", "a%20b"); // a bmanager.invoke("base64Encode", "hello"); // aGVsbG8=manager.invoke("base64Decode", "aGVsbG8="); // hellomanager.invoke("md5", "hello"); // 5d41402abc4b2a76b9719d911017c592数学运算(62 个)
Section titled “数学运算(62 个)”四则与取整:
// 四则(多参数依次参与运算)manager.invoke("add", 10, 20); // 30.0manager.invoke("subtract", 30, 10); // 20.0manager.invoke("multiply", 3, 4); // 12.0manager.invoke("divide", 10, 4); // 2.5manager.invoke("mod", 10, 3); // 1.0manager.invoke("abs", -5); // 绝对值 5
// 取整manager.invoke("round", 3.5); // 4.0manager.invoke("roundTo", 3.14159, 2); // 3.14manager.invoke("ceil", 3.1); // 4.0manager.invoke("ceilTo", 3.11, 1); // 3.2manager.invoke("floor", 3.9); // 3.0manager.invoke("floorTo", 3.19, 1); // 3.1manager.invoke("signum", -8); // -1.0聚合与统计:
// 求和、均值、极值manager.invoke("sum", 1, 2, 3); // 6.0manager.invoke("avg", 10, 20, 30); // 20.0manager.invoke("max", 3, 1, 2); // 3.0manager.invoke("min", 3, 1, 2); // 1.0manager.invoke("greatest", 3, 7, 2); // 7.0manager.invoke("least", 3, 7, 2); // 2.0manager.invoke("product", 2, 3, 4); // 24.0manager.invoke("range", 1, 9, 3); // 8.0
// 中位数、众数、百分位(返回对应统计值)manager.invoke("median", 1, 2, 3, 4); // 2.5manager.invoke("mode", 1, 1, 2);manager.invoke("percentile", 1, 2, 3, 4, 5, 6, 7, 8, 9, 50);
// 方差与标准差(返回对应统计值)manager.invoke("variance", 2, 4, 4, 4, 5, 5, 7, 9);manager.invoke("stdDev", 2, 4, 4, 4, 5, 5, 7, 9);
// 计数manager.invoke("count", 1, 2, 3); // 3manager.invoke("countNonNull", null, 1, null); // 1manager.invoke("countDistinct", 1, 1, 2, 3, 3); // 3manager.invoke("isNumber", "12.3"); // true幂、对数与三角函数:
// 幂与开方manager.invoke("pow", 2, 10); // 1024.0manager.invoke("sqrt", 16); // 4.0manager.invoke("exp", 1); // 2.718281828459045manager.invoke("expm1", 0); // 0.0
// 对数manager.invoke("log", Math.E); // 1.0manager.invoke("log10", 1000); // 3.0manager.invoke("log1p", 0); // 0.0
// 三角函数(角度参数为弧度)manager.invoke("sin", Math.PI / 2); // 1.0manager.invoke("cos", 0); // 1.0manager.invoke("tan", Math.PI / 4); // 0.9999999999999999manager.invoke("asin", 1); // 1.5707963267948966(π/2)manager.invoke("acos", 1); // 0.0manager.invoke("atan", 1); // 0.7853981633974483(π/4)manager.invoke("atan2", 1, 1); // 0.7853981633974483manager.invoke("sinh", 0); // 0.0manager.invoke("cosh", 0); // 1.0manager.invoke("tanh", 0); // 0.0
// 角度弧度互换manager.invoke("toRadians", 180); // 3.141592653589793manager.invoke("toDegrees", Math.PI); // 180.0
// 常量manager.invoke("pi"); // 3.141592653589793manager.invoke("e"); // 2.718281828459045类型转换与进制:
// 数值类型转换(第二个参数为默认值)manager.invoke("toInt", "12"); // 12manager.invoke("toLong", "12"); // 12manager.invoke("toFloat", "12"); // 12.0manager.invoke("toDouble", "12"); // 12.0
// 进制转换manager.invoke("toBinary", 10); // 1010manager.invoke("toHex", 255); // ffmanager.invoke("toOctal", 8); // 10manager.invoke("parseBinary", "1010"); // 10manager.invoke("parseHex", "ff"); // 255
// 按 pattern 输出数字字符串manager.invoke("toNumberString", 3.14, "0.0");
// 浮点数最小精度单位manager.invoke("ulp", 1.0); // 2.220446049250313E-16日期时间(38 个)
Section titled “日期时间(38 个)”下列 demo 以固定基准日期调用:date = 2026-09-30,datetime = 2026-09-30 10:30:00(均为周三)。
import java.time.LocalDate;import java.time.LocalDateTime;
LocalDate date = LocalDate.of(2026, 9, 30);LocalDateTime datetime = LocalDateTime.of(2026, 9, 30, 10, 30, 0);
// 当前时间manager.invoke("now"); // 当前 LocalDateTimemanager.invoke("today"); // 当前 LocalDatemanager.invoke("timestamp"); // 当前毫秒时间戳
// 取年/月/日(不传参数则取当前日期)manager.invoke("year", date); // 2026manager.invoke("month", date); // 9manager.invoke("day", date); // 30
// 取时/分/秒manager.invoke("hour", datetime); // 10manager.invoke("minute", datetime); // 30manager.invoke("second", datetime); // 0
// 周/年中序号:周一=1manager.invoke("dayOfWeek", date); // 3(周三)manager.invoke("dayOfYear", date); // 273manager.invoke("weekOfYear", date); // 年内周序号日期运算与格式化:
// 日期加减manager.invoke("addDays", date, 7); // 2026-10-07manager.invoke("addMonths", date, 1); // 2026-10-30manager.invoke("addYears", date, 1); // 2027-09-30manager.invoke("addHours", datetime, 2); // 2026-09-30 12:30manager.invoke("addMinutes", datetime, 15); // 2026-09-30 10:45manager.invoke("addSeconds", datetime, 30); // 2026-09-30 10:30:30
// 格式化与解析manager.invoke("formatDate", date, "yyyy/MM/dd"); // 2026/09/30manager.invoke("parseDate", "2026-09-30", "yyyy-MM-dd"); // LocalDatemanager.invoke("toIsoString", date); // 2026-09-30边界、比较与差值:
// 起止边界manager.invoke("startOfDay", date); // 2026-09-30 00:00manager.invoke("endOfDay", date); // 2026-09-30 23:59:59manager.invoke("startOfMonth", date); // 2026-09-01manager.invoke("endOfMonth", date); // 2026-09-30manager.invoke("startOfYear", date); // 2026-01-01manager.invoke("endOfYear", date); // 2026-12-31
// 先后与同日判断manager.invoke("isAfter", date, date.minusDays(1)); // truemanager.invoke("isBefore", date, date.plusDays(1)); // truemanager.invoke("isSameDay", datetime, date); // truemanager.invoke("isWeekend", date); // falsemanager.invoke("isLeapYear", 2026); // falsemanager.invoke("isDate", "2026-09-30"); // true(可解析为日期)
// 差值manager.invoke("daysBetween", date, date.plusDays(10)); // 10manager.invoke("hoursBetween", datetime, datetime.plusHours(5)); // 5manager.invoke("monthsBetween", date, date.plusMonths(3)); // 3manager.invoke("yearsBetween", date, date.plusYears(2)); // 2
// 年龄:按出生日期与参考日期计算(不传参考日期则取今天)manager.invoke("age", LocalDate.of(2000, 1, 1), date);条件判断(14 个)
Section titled “条件判断(14 个)”比较运算与范围:
// 相等 / 不等(第三个参数控制是否忽略大小写)manager.invoke("eq", 1, 1); // truemanager.invoke("eq", "Abc", "abc", true); // truemanager.invoke("ne", 1, 2); // true
// 大小比较manager.invoke("gt", 2, 1); // truemanager.invoke("gte", 2, 2); // truemanager.invoke("lt", 1, 2); // truemanager.invoke("lte", 2, 2); // true
// 范围:第四个参数控制是否包含边界manager.invoke("between", 5, 1, 10); // truemanager.invoke("between", 10, 1, 10, false); // false(不含上边界)分支与空值:
// 三元判断manager.invoke("if", true, "通过", "不通过"); // 通过
// 多条件:条件与结果成对出现,最后一个为兜底值int score = 75;manager.invoke("ifElse", score >= 90, "A", score >= 60, "B", "C"); // Bmanager.invoke("caseWhen", score < 60, "不及格", score < 80, "良", "优"); // 良
// 值匹配分支int status = 2;manager.invoke("switch", status, 1, "待支付", 2, "已支付", "已取消"); // 已支付
// 空值处理manager.invoke("coalesce", null, null, "default"); // defaultmanager.invoke("nvl", null, 0); // 0manager.invoke("defaultIfNull", null, "默认值"); // 默认值类型转换(4 个)
Section titled “类型转换(4 个)”// 字符串转布尔manager.invoke("toBoolean", "true"); // true
// 字符串转日期(第二个参数为解析格式)manager.invoke("toDate", "2026-09-30", "yyyy-MM-dd"); // LocalDatemanager.invoke("toDateTime", "2026-09-30 10:30:00", "yyyy-MM-dd HH:mm:ss"); // LocalDateTime
// 转短整数(第二个参数为默认值)manager.invoke("toShort", "12"); // 12业务脱敏与校验(13 个)
Section titled “业务脱敏与校验(13 个)”身份证相关:
String idCard = "11010119900307077X";
// 校验与信息提取manager.invoke("idCardValidate", idCard); // 是否有效manager.invoke("idCardInfo", idCard, "region"); // 归属地manager.invoke("idCardInfo", idCard, "age"); // 年龄manager.invoke("idCardGender", idCard, "M/F"); // M(按 format 返回)manager.invoke("idCardBirthday", idCard, "yyyy-MM-dd"); // 1990-03-07manager.invoke("idCardAge", idCard); // 年龄数值手机、邮箱、银行卡与性别:
// 手机manager.invoke("phoneValidate", "13812345678"); // truemanager.invoke("phoneMask", "13812345678"); // 138****5678manager.invoke("phoneMask", "13812345678", 3, 4); // 同上(默认保留前3后4)manager.invoke("phoneInfo", "13812345678", "carrier"); // 运营商信息
// 邮箱
// 银行卡(默认保留前4后4)manager.invoke("bankCardValidate", "6222021234567890"); // 是否有效(Luhn)manager.invoke("bankCardMask", "6222021234567890"); // 6222********7890
// 性别码值转名称:支持 M/F、1/0、男/女、male/femalemanager.invoke("genderName", "M"); // 男集合处理(3 个)
Section titled “集合处理(3 个)”import java.util.Arrays;import java.util.List;
List<String> list = Arrays.asList("a", "b", "c");
// 空判断:支持 String / Collection / Map / Arraymanager.invoke("isEmpty", ""); // truemanager.invoke("isEmpty", list); // false
// 长度:集合、数组、Map、字符串均可manager.invoke("size", list); // 3
// 按分隔符连接集合元素manager.invoke("join", list, "-"); // a-b-c数组判断(1 个)
Section titled “数组判断(1 个)”// 判断是否为数组或列表manager.invoke("isArray", new int[]{1, 2, 3}); // truemanager.invoke("isArray", "abc"); // false位运算(3 个)
Section titled “位运算(3 个)”// 6 的二进制为 110,3 为 011manager.invoke("bitAnd", 6, 3); // 2(110 & 011 = 010)manager.invoke("bitOr", 6, 3); // 7(110 | 011 = 111)manager.invoke("bitXor", 6, 3); // 5(110 ^ 011 = 101)布尔判断(1 个)
Section titled “布尔判断(1 个)”// 判断是否为布尔值manager.invoke("isBoolean", true); // truemanager.invoke("isBoolean", "true"); // falseAES 加解密(3 个)
Section titled “AES 加解密(3 个)”// 生成 Base64 密钥;加密、解密使用同一把密钥String aesKey = (String) manager.invoke("aesGenerateKey");String aesCipher = (String) manager.invoke("aesEncrypt", "敏感数据", aesKey);String aesPlain = (String) manager.invoke("aesDecrypt", aesCipher, aesKey);// aesPlain = 敏感数据RSA 加解密(3 个)
Section titled “RSA 加解密(3 个)”import java.util.Map;
// 生成密钥对,返回 Map:含 publicKey、privateKey(均为 Base64)Map<?, ?> rsaPair = (Map<?, ?>) manager.invoke("rsaGenerateKeyPair");String rsaCipher = (String) manager.invoke("rsaEncrypt", "敏感数据", rsaPair.get("publicKey"));String rsaPlain = (String) manager.invoke("rsaDecrypt", rsaCipher, rsaPair.get("privateKey"));// rsaPlain = 敏感数据ECC 加解密(3 个)
Section titled “ECC 加解密(3 个)”import java.util.Map;
// 生成 ECC 密钥对,返回 Map:含 publicKey、privateKeyMap<?, ?> eccPair = (Map<?, ?>) manager.invoke("eccGenerateKeyPair");String eccCipher = (String) manager.invoke("eccEncrypt", "敏感数据", eccPair.get("publicKey"));String eccPlain = (String) manager.invoke("eccDecrypt", eccCipher, eccPair.get("privateKey"));// eccPlain = 敏感数据随机数(13 个)
Section titled “随机数(13 个)”import java.util.Arrays;import java.util.List;
// 随机整数/长整数/浮点数:支持无参、单上界、上下界三种形式manager.invoke("randomInt"); // 随机整数manager.invoke("randomInt", 100); // [0, 100)manager.invoke("randomInt", 1, 100); // [1, 100)manager.invoke("randomLong", 1L, 1000L); // [1, 1000)manager.invoke("randomDouble", 0.0, 1.0); // [0.0, 1.0)
// 按概率生成布尔值:参数为 true 的概率manager.invoke("randomBoolean"); // 等概率manager.invoke("randomBoolean", 0.8); // 80% 为 true
// 随机字符串 / UUIDmanager.invoke("randomString", 8); // 8 位随机字符串manager.invoke("randomUUID"); // 标准 UUIDmanager.invoke("randomUUID", true); // 去掉连字符的 UUID
// 随机颜色:type 支持 hex / rgb / presetmanager.invoke("randomColor"); // #RRGGBBmanager.invoke("randomColor", "rgb"); // rgb(r, g, b)manager.invoke("randomColor", "preset"); // 预置颜色之一
// 随机日期:在起止日期之间(第三个参数为日期格式)manager.invoke("randomDate", "2026-01-01", "2026-12-31", "yyyy-MM-dd");
// 随机选取List<String> candidates = Arrays.asList("a", "b", "c", "d");manager.invoke("randomChoice", candidates); // 列表中随机一个manager.invoke("random", candidates); // 同上,数组/列表随机取一manager.invoke("randomSample", candidates, 2); // 随机取 2 个manager.invoke("randomIntArray", 5, 1, 10); // 长度为 5 的随机整数数组
// 打乱顺序(返回打乱后的列表)manager.invoke("shuffle", candidates);JSON 处理(1 个)
Section titled “JSON 处理(1 个)”// 对象序列化为 JSON 字符串manager.invoke("toJson", userObject); // JSON 文本扩展转换(9 个)
Section titled “扩展转换(9 个)”// 强制类型转换:第二个参数为目标 Classmanager.invoke("cast", "123", Integer.class); // 123
// 数字格式化与反解析(pattern 为 DecimalFormat 格式)manager.invoke("formatNumber", 1234.567, "#,##0.00"); // 1,234.57manager.invoke("parseNumber", "1,234.57", "#,##0.00"); // 1234.57
// 货币 / 百分比(第二个参数分别为 locale、保留小数位)manager.invoke("toCurrency", 1234.5); // 货币格式文本manager.invoke("toPercentage", 0.85, 2); // 85.00%
// 包装为数组 / 列表manager.invoke("toArray", 1, 2, 3); // [1, 2, 3]manager.invoke("toList", 1, 2, 3); // [1, 2, 3]
// 类型名称manager.invoke("typeOf", "abc"); // String
// 范围判断(与 condition 类 between 用法一致)manager.invoke("between", 5, 1, 10); // true几何与向量(22 个)
Section titled “几何与向量(22 个)”图形面积与周长:
// 圆:πr² 与 2πrmanager.invoke("areaCircle", 2); // 12.566370614359172manager.invoke("circumference", 2); // 12.566370614359172
// 矩形:长 × 宽manager.invoke("areaRectangle", 3, 4); // 12.0
// 三角形:底 × 高 / 2;三边形式按海伦公式计算manager.invoke("areaTriangle", 3, 4); // 6.0manager.invoke("areaTriangle", 3, 4, 5); // 6.0
// 数值限幅manager.invoke("clamp", 15, 0, 10); // 10数论与排列:
// 阶乘、组合、排列manager.invoke("factorial", 5); // 120manager.invoke("combination", 5, 2); // 10(C(5,2))manager.invoke("permutation", 5, 2); // 20(P(5,2))manager.invoke("fibonacci", 10); // 55
// 公约数、公倍数manager.invoke("gcd", 12, 18); // 6manager.invoke("lcm", 4, 6); // 12
// 素数与 2 的幂manager.invoke("isPrime", 7); // truemanager.invoke("isPowerOfTwo", 16); // true
// 直角三角形斜边长manager.invoke("hypot", 3, 4); // 5.0插值、映射与向量:
import java.util.Arrays;
// 线性插值:t=0 返回 a,t=1 返回 bmanager.invoke("lerp", 0, 10, 0.5); // 5.0
// 数值范围映射:把 [fromLow, fromHigh] 映射到 [toLow, toHigh]manager.invoke("map", 5, 0, 10, 0, 100); // 50.0
// 两点距离:2D 四个参数 / 3D 六个参数manager.invoke("distance", 0, 0, 3, 4); // 5.0
// 向量叉积(2D 标量):x1*y2 - y1*x2manager.invoke("cross", 1, 0, 0, 1); // 1
// 向量点积:向量以 List 传入manager.invoke("dot", Arrays.asList(1, 2), Arrays.asList(3, 4)); // 11.0
// 复数运算:返回 [实部, 虚部]manager.invoke("complexAdd", 1, 2, 3, 4); // [4, 6]manager.invoke("complexMultiply", 1, 2, 3, 4); // [-5, 10]
// 矩阵加法:矩阵以二维 List 传入manager.invoke("matrixAdd", Arrays.asList(Arrays.asList(1, 2)), Arrays.asList(Arrays.asList(3, 4))); // [[4, 6]]码值翻译(1 个)
Section titled “码值翻译(1 个)”import com.github.paohaijiao.param.JContext;
// 字典数据存放在 JContext 中:key 为码值,value 为显示文本JContext context = new JContext();context.put("M", "男");context.put("F", "女");
// translate(context, 码值) 返回字典文本manager.invoke("translate", context, "M"); // 男manager.invoke("translate", context, "F"); // 女自定义转换函数
Section titled “自定义转换函数”扩展只需三步:实现 → 注册 → 调用。
第一步:实现函数提供者。 推荐继承 JQuickBaseFunctionFunctionProvider,可直接使用 asString / asInt / asDouble / validateArgCount 等参数处理工具。
package com.example.function;
import com.github.paohaijiao.function.domain.JQuickBaseFunctionFunctionProvider;
import java.util.List;
/** * 自定义函数:姓名脱敏 * maskName("张三") -> "张**" */public class MaskNameFunctionProvider extends JQuickBaseFunctionFunctionProvider {
public MaskNameFunctionProvider() { // 构造参数:函数名(调用时使用)、描述(前缀决定分组归属) super("maskName", "[业务] 姓名脱敏,仅保留姓氏"); }
@Override public Object invoke(List<Object> args) { validateArgCount(args, 1); String name = asString(args.get(0)); if (name == null || name.length() <= 1) { return name; } return name.charAt(0) + "**"; }}第二步:注册 SPI。 创建文件 src/main/resources/META-INF/services/com.github.paohaijiao.function.core.JQuickMethodFunctionProvider,每行写一个实现类的全限定名:
com.example.function.MaskNameFunctionProvider第三步:按名称调用。
Object masked = manager.invoke("maskName", "张三"); // 张**简单函数也可以直接用 Lambda 注册,或用同名函数覆盖内置实现:
// 注册一个全新函数manager.registerInvoker("doubleIt", args -> ((Number) args.get(0)).doubleValue() * 2);
// 覆盖内置的 toUpper:返回结果追加感叹号manager.registerOrReplaceInvoker("toUpper", args -> String.valueOf(args.get(0)).toUpperCase() + "!", "[覆盖] 自定义 toUpper");搭配 JQuick-SQL:函数即 SQL 函数
Section titled “搭配 JQuick-SQL:函数即 SQL 函数”jquick-sql 已直接依赖 jquick-transform-function。内置函数与按 SPI 注册的自定义函数,均可直接写在 SQL 语句中,由执行引擎按函数名从注册中心解析:
// 内置/自定义函数直接用于查询,无需额外注册动作JQuickDataSet result = sql.execute( "SELECT name, toCamelCase(name, '_') AS camel FROM users");在 SQL 解析与审计场景中,函数调用本身是 AST 中的类型化节点,配合达梦、KingbaseES 等国产数据库做 SQL 审计、迁移改写时,可统一治理自定义函数。
搭配 jquick-excel:导入导出的数据清洗
Section titled “搭配 jquick-excel:导入导出的数据清洗”jquick-excel 已直接依赖 jquick-transform-function。Excel DSL 中 TRANSFORM 表达式求值时会先按函数名从本组件的 SPI 注册中心查找,因此全部 259 个内置函数及自定义函数可直接用于导入导出:
-- 导出前:手机号脱敏、姓名脱敏EXPORT WITH { TRANSFORM = {"phone": "phoneMask(phone)", "name": "maskName(name)"}}导入时同理,可在读取入库前完成码值翻译、格式归一与字段清洗,业务侧无需再写转换代码。
- 数据同步(ETL):异构系统间同步时做类型转换、码值字典翻译、格式归一。
- 报表导出:Excel / PDF 报表导出前对手机号、银行卡、身份证等敏感字段脱敏。
- 数据库字段值转换:在 SQL 内直接调用函数,把库内码值(如
1/0)转换为展示文本(如是/否),适配达梦、KingbaseES 等国产库。 - 数据清洗:对导入数据统一执行去空格、大小写规范、空值兜底、日期格式化等清洗规则。
仓库与 Issue
Section titled “仓库与 Issue”- GitHub 仓库:https://github.com/paohaijiao/jquick-transform-function
- Issue 反馈:https://github.com/paohaijiao/jquick-transform-function/issues
- 开源协议:Apache License 2.0