From e2de04d36f488138eb7dfd02126b078453bce775 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 11 Jun 2021 13:17:35 +0800 Subject: [PATCH] add method --- CHANGELOG.md | 4 +- README-EN.md | 41 +- README.md | 3 +- .../cn/hutool/core/text/CharSequenceUtil.java | 12 +- .../java/cn/hutool/core/text/StrSpliter.java | 519 +---------------- .../java/cn/hutool/core/text/StrSplitter.java | 521 ++++++++++++++++++ .../java/cn/hutool/core/util/NumberUtil.java | 28 + .../java/cn/hutool/core/img/ImgUtilTest.java | 1 + .../cn/hutool/core/lang/StrSpliterTest.java | 20 +- .../cn/hutool/core/util/NumberUtilTest.java | 18 + .../main/java/cn/hutool/db/sql/Condition.java | 4 +- 11 files changed, 617 insertions(+), 554 deletions(-) create mode 100644 hutool-core/src/main/java/cn/hutool/core/text/StrSplitter.java diff --git a/CHANGELOG.md b/CHANGELOG.md index ef7905c8e..09f630c02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,12 +3,14 @@ ------------------------------------------------------------------------------------------------------------- -# 5.7.0 (2021-06-10) +# 5.7.0 (2021-06-11) ### 🐣新特性 * 【jwt 】 添加JWT模块,实现了JWT的创建、解析和验证 * 【crypto 】 SymmetricCrypto增加update方法(pr#1642@Github) * 【crypto 】 MacEngine增加接口update,doFinal,reset等接口 +* 【core 】 StrSpliter更名为StrSplitter +* 【core 】 NumberUtil的decimalFormat增加数字检查 ### 🐞Bug修复 diff --git a/README-EN.md b/README-EN.md index a791ae9dd..3ecfb78c7 100644 --- a/README-EN.md +++ b/README-EN.md @@ -80,26 +80,27 @@ Hutool exists to reduce code search costs and avoid bugs caused by imperfect cod ## 🛠️Module A Java-based tool class for files, streams, encryption and decryption, transcoding, regular, thread, XML and other JDK methods for encapsulation,composing various Util tool classes, as well as providing the following modules: -| module | description | -| -------------------|---------------------------------------------------------------------------------- | -| hutool-aop | JDK dynamic proxy encapsulation to provide non-IOC faceting support | -| hutool-bloomFilter | Bloom filtering to provide some Hash algorithm Bloom filtering | -| hutool-cache | Simple cache | -| hutool-core | Core, including Bean operations, dates, various Utils, etc. | -| hutool-cron | Task scheduling with Cron expressions | -| hutool-crypto | Provides symmetric, asymmetric and digest algorithm encapsulation | -| hutool-db | Db operations based on ActiveRecord thinking. | -| hutool-dfa | DFA models, such as multi-keyword lookups | -| hutool-extra | Extension modules, third-party wrappers (template engine, mail, servlet, QR code, Emoji, FTP, word splitting, etc.) | -| hutool-http | Http client | -| hutool-log | Log (facade) | -| hutool-script | Script execution encapsulation, e.g. Javascript | -| hutool-setting | Stronger Setting Profile tools and Properties tools | -| hutool-system | System parameter tools (JVM information, etc.) | -| hutool-json | JSON | -| hutool-captcha | Image Captcha | -| hutool-poi | Tools for working with Excel and Word in POI | -| hutool-socket | Java-based tool classes for NIO and AIO sockets | +| module | description | +| -------------------|-------------------------------------------------------------------------------------------------------------------------| +| hutool-aop | JDK dynamic proxy encapsulation to provide non-IOC faceting support | +| hutool-bloomFilter | Bloom filtering to provide some Hash algorithm Bloom filtering | +| hutool-cache | Simple cache | +| hutool-core | Core, including Bean operations, dates, various Utils, etc. | +| hutool-cron | Task scheduling with Cron expressions | +| hutool-crypto | Provides symmetric, asymmetric and digest algorithm encapsulation | +| hutool-db | Db operations based on ActiveRecord thinking. | +| hutool-dfa | DFA models, such as multi-keyword lookups | +| hutool-extra | Extension modules, third-party wrappers (template engine, mail, servlet, QR code, Emoji, FTP, word splitting, etc.) | +| hutool-http | Http client | +| hutool-log | Log (facade) | +| hutool-script | Script execution encapsulation, e.g. Javascript | +| hutool-setting | Stronger Setting Profile tools and Properties tools | +| hutool-system | System parameter tools (JVM information, etc.) | +| hutool-json | JSON | +| hutool-captcha | Image Captcha | +| hutool-poi | Tools for working with Excel and Word in POI | +| hutool-socket | Java-based tool classes for NIO and AIO sockets | +| hutool-jwt | JSON Web Token (JWT) implement | Each module can be introduced individually, or all modules can be introduced by introducing `hutool-all` as required. diff --git a/README.md b/README.md index 1dcadd31e..f0117a188 100644 --- a/README.md +++ b/README.md @@ -89,13 +89,14 @@ Hutool的存在就是为了减少代码搜索成本,避免网络上参差不 | hutool-extra | 扩展模块,对第三方封装(模板引擎、邮件、Servlet、二维码、Emoji、FTP、分词等) | | hutool-http | 基于HttpUrlConnection的Http客户端封装 | | hutool-log | 自动识别日志实现的日志门面 | -| hutool-script | 脚本执行封装,例如Javascript | +| hutool-script | 脚本执行封装,例如Javascript | | hutool-setting | 功能更强大的Setting配置文件和Properties封装 | | hutool-system | 系统参数调用封装(JVM信息等) | | hutool-json | JSON实现 | | hutool-captcha | 图片验证码实现 | | hutool-poi | 针对POI中Excel和Word的封装 | | hutool-socket | 基于Java的NIO和AIO的Socket封装 | +| hutool-jwt | JSON Web Token (JWT)封装实现 | 可以根据需求对每个模块单独引入,也可以通过引入`hutool-all`方式引入所有模块。 diff --git a/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java b/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java index bf7cea388..ef892af83 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java @@ -1702,7 +1702,7 @@ public class CharSequenceUtil { return new String[]{}; } - return StrSpliter.splitToArray(str.toString(), str(separator), 0, false, false); + return StrSplitter.splitToArray(str.toString(), str(separator), 0, false, false); } /** @@ -1728,7 +1728,7 @@ public class CharSequenceUtil { if (null == str) { return new String[]{}; } - return StrSpliter.splitToArray(str.toString(), separator, limit, false, false); + return StrSplitter.splitToArray(str.toString(), separator, limit, false, false); } /** @@ -1822,7 +1822,7 @@ public class CharSequenceUtil { if (null == str) { return new ArrayList<>(0); } - return StrSpliter.split(str.toString(), separator, limit, isTrim, ignoreEmpty); + return StrSplitter.split(str.toString(), separator, limit, isTrim, ignoreEmpty); } /** @@ -1855,7 +1855,7 @@ public class CharSequenceUtil { return new ArrayList<>(0); } final String separatorStr = (null == separator) ? null : separator.toString(); - return StrSpliter.split(str.toString(), separatorStr, limit, isTrim, ignoreEmpty); + return StrSplitter.split(str.toString(), separatorStr, limit, isTrim, ignoreEmpty); } /** @@ -1877,13 +1877,13 @@ public class CharSequenceUtil { * @param str 字符串 * @param len 每一个小节的长度 * @return 截取后的字符串数组 - * @see StrSpliter#splitByLength(String, int) + * @see StrSplitter#splitByLength(String, int) */ public static String[] split(CharSequence str, int len) { if (null == str) { return new String[]{}; } - return StrSpliter.splitByLength(str.toString(), len); + return StrSplitter.splitByLength(str.toString(), len); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/text/StrSpliter.java b/hutool-core/src/main/java/cn/hutool/core/text/StrSpliter.java index 0173d1393..a7b6a3660 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/StrSpliter.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/StrSpliter.java @@ -1,520 +1,11 @@ package cn.hutool.core.text; -import cn.hutool.core.lang.PatternPool; -import cn.hutool.core.util.CharUtil; -import cn.hutool.core.util.NumberUtil; -import cn.hutool.core.util.StrUtil; - -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - /** * 字符串切分器 - *x - * @author Looly + * + * @author looly + * @deprecated 此类拼写错误,请使用 {@link StrSplitter} */ -public class StrSpliter { - - //---------------------------------------------------------------------------------------------- Split by char - - /** - * 切分字符串路径,仅支持Unix分界符:/ - * - * @param str 被切分的字符串 - * @return 切分后的集合 - * @since 3.0.8 - */ - public static List splitPath(String str) { - return splitPath(str, 0); - } - - /** - * 切分字符串路径,仅支持Unix分界符:/ - * - * @param str 被切分的字符串 - * @return 切分后的集合 - * @since 3.0.8 - */ - public static String[] splitPathToArray(String str) { - return toArray(splitPath(str)); - } - - /** - * 切分字符串路径,仅支持Unix分界符:/ - * - * @param str 被切分的字符串 - * @param limit 限制分片数 - * @return 切分后的集合 - * @since 3.0.8 - */ - public static List splitPath(String str, int limit) { - return split(str, StrUtil.C_SLASH, limit, true, true); - } - - /** - * 切分字符串路径,仅支持Unix分界符:/ - * - * @param str 被切分的字符串 - * @param limit 限制分片数 - * @return 切分后的集合 - * @since 3.0.8 - */ - public static String[] splitPathToArray(String str, int limit) { - return toArray(splitPath(str, limit)); - } - - /** - * 切分字符串 - * - * @param str 被切分的字符串 - * @param separator 分隔符字符 - * @param ignoreEmpty 是否忽略空串 - * @return 切分后的集合 - * @since 3.2.1 - */ - public static List splitTrim(String str, char separator, boolean ignoreEmpty) { - return split(str, separator, 0, true, ignoreEmpty); - } - - /** - * 切分字符串 - * - * @param str 被切分的字符串 - * @param separator 分隔符字符 - * @param isTrim 是否去除切分字符串后每个元素两边的空格 - * @param ignoreEmpty 是否忽略空串 - * @return 切分后的集合 - * @since 3.0.8 - */ - public static List split(String str, char separator, boolean isTrim, boolean ignoreEmpty) { - return split(str, separator, 0, isTrim, ignoreEmpty); - } - - /** - * 切分字符串,大小写敏感,去除每个元素两边空白符 - * - * @param str 被切分的字符串 - * @param separator 分隔符字符 - * @param limit 限制分片数,-1不限制 - * @param ignoreEmpty 是否忽略空串 - * @return 切分后的集合 - * @since 3.0.8 - */ - public static List splitTrim(String str, char separator, int limit, boolean ignoreEmpty) { - return split(str, separator, limit, true, ignoreEmpty, false); - } - - /** - * 切分字符串,大小写敏感 - * - * @param str 被切分的字符串 - * @param separator 分隔符字符 - * @param limit 限制分片数,-1不限制 - * @param isTrim 是否去除切分字符串后每个元素两边的空格 - * @param ignoreEmpty 是否忽略空串 - * @return 切分后的集合 - * @since 3.0.8 - */ - public static List split(String str, char separator, int limit, boolean isTrim, boolean ignoreEmpty) { - return split(str, separator, limit, isTrim, ignoreEmpty, false); - } - - /** - * 切分字符串,忽略大小写 - * - * @param str 被切分的字符串 - * @param separator 分隔符字符 - * @param limit 限制分片数,-1不限制 - * @param isTrim 是否去除切分字符串后每个元素两边的空格 - * @param ignoreEmpty 是否忽略空串 - * @return 切分后的集合 - * @since 3.2.1 - */ - public static List splitIgnoreCase(String str, char separator, int limit, boolean isTrim, boolean ignoreEmpty) { - return split(str, separator, limit, isTrim, ignoreEmpty, true); - } - - /** - * 切分字符串 - * - * @param str 被切分的字符串 - * @param separator 分隔符字符 - * @param limit 限制分片数,-1不限制 - * @param isTrim 是否去除切分字符串后每个元素两边的空格 - * @param ignoreEmpty 是否忽略空串 - * @param ignoreCase 是否忽略大小写 - * @return 切分后的集合 - * @since 3.2.1 - */ - public static List split(String str, char separator, int limit, boolean isTrim, boolean ignoreEmpty, boolean ignoreCase) { - if (StrUtil.isEmpty(str)) { - return new ArrayList<>(0); - } - if (limit == 1) { - return addToList(new ArrayList<>(1), str, isTrim, ignoreEmpty); - } - - final ArrayList list = new ArrayList<>(limit > 0 ? limit : 16); - int len = str.length(); - int start = 0;//切分后每个部分的起始 - for (int i = 0; i < len; i++) { - if (NumberUtil.equals(separator, str.charAt(i), ignoreCase)) { - addToList(list, str.substring(start, i), isTrim, ignoreEmpty); - start = i + 1;//i+1同时将start与i保持一致 - - //检查是否超出范围(最大允许limit-1个,剩下一个留给末尾字符串) - if (limit > 0 && list.size() > limit - 2) { - break; - } - } - } - return addToList(list, str.substring(start, len), isTrim, ignoreEmpty);//收尾 - } - - /** - * 切分字符串为字符串数组 - * - * @param str 被切分的字符串 - * @param separator 分隔符字符 - * @param limit 限制分片数 - * @param isTrim 是否去除切分字符串后每个元素两边的空格 - * @param ignoreEmpty 是否忽略空串 - * @return 切分后的集合 - * @since 3.0.8 - */ - public static String[] splitToArray(String str, char separator, int limit, boolean isTrim, boolean ignoreEmpty) { - return toArray(split(str, separator, limit, isTrim, ignoreEmpty)); - } - - //---------------------------------------------------------------------------------------------- Split by String - - /** - * 切分字符串,不忽略大小写 - * - * @param str 被切分的字符串 - * @param separator 分隔符字符串 - * @param isTrim 是否去除切分字符串后每个元素两边的空格 - * @param ignoreEmpty 是否忽略空串 - * @return 切分后的集合 - * @since 3.0.8 - */ - public static List split(String str, String separator, boolean isTrim, boolean ignoreEmpty) { - return split(str, separator, -1, isTrim, ignoreEmpty, false); - } - - /** - * 切分字符串,去除每个元素两边空格,忽略大小写 - * - * @param str 被切分的字符串 - * @param separator 分隔符字符串 - * @param ignoreEmpty 是否忽略空串 - * @return 切分后的集合 - * @since 3.2.1 - */ - public static List splitTrim(String str, String separator, boolean ignoreEmpty) { - return split(str, separator, true, ignoreEmpty); - } - - /** - * 切分字符串,不忽略大小写 - * - * @param str 被切分的字符串 - * @param separator 分隔符字符串 - * @param limit 限制分片数 - * @param isTrim 是否去除切分字符串后每个元素两边的空格 - * @param ignoreEmpty 是否忽略空串 - * @return 切分后的集合 - * @since 3.0.8 - */ - public static List split(String str, String separator, int limit, boolean isTrim, boolean ignoreEmpty) { - return split(str, separator, limit, isTrim, ignoreEmpty, false); - } - - /** - * 切分字符串,去除每个元素两边空格,忽略大小写 - * - * @param str 被切分的字符串 - * @param separator 分隔符字符串 - * @param limit 限制分片数 - * @param ignoreEmpty 是否忽略空串 - * @return 切分后的集合 - * @since 3.2.1 - */ - public static List splitTrim(String str, String separator, int limit, boolean ignoreEmpty) { - return split(str, separator, limit, true, ignoreEmpty); - } - - /** - * 切分字符串,忽略大小写 - * - * @param str 被切分的字符串 - * @param separator 分隔符字符串 - * @param limit 限制分片数 - * @param isTrim 是否去除切分字符串后每个元素两边的空格 - * @param ignoreEmpty 是否忽略空串 - * @return 切分后的集合 - * @since 3.2.1 - */ - public static List splitIgnoreCase(String str, String separator, int limit, boolean isTrim, boolean ignoreEmpty) { - return split(str, separator, limit, isTrim, ignoreEmpty, true); - } - - /** - * 切分字符串,去除每个元素两边空格,忽略大小写 - * - * @param str 被切分的字符串 - * @param separator 分隔符字符串 - * @param limit 限制分片数 - * @param ignoreEmpty 是否忽略空串 - * @return 切分后的集合 - * @since 3.2.1 - */ - public static List splitTrimIgnoreCase(String str, String separator, int limit, boolean ignoreEmpty) { - return split(str, separator, limit, true, ignoreEmpty, true); - } - - /** - * 切分字符串 - * - * @param str 被切分的字符串 - * @param separator 分隔符字符串 - * @param limit 限制分片数 - * @param isTrim 是否去除切分字符串后每个元素两边的空格 - * @param ignoreEmpty 是否忽略空串 - * @param ignoreCase 是否忽略大小写 - * @return 切分后的集合 - * @since 3.2.1 - */ - public static List split(String str, String separator, int limit, boolean isTrim, boolean ignoreEmpty, boolean ignoreCase) { - if (StrUtil.isEmpty(str)) { - return new ArrayList<>(0); - } - if (limit == 1) { - return addToList(new ArrayList<>(1), str, isTrim, ignoreEmpty); - } - - if (StrUtil.isEmpty(separator)) {//分隔符为空时按照空白符切分 - return split(str, limit); - } else if (separator.length() == 1) {//分隔符只有一个字符长度时按照单分隔符切分 - return split(str, separator.charAt(0), limit, isTrim, ignoreEmpty, ignoreCase); - } - - final ArrayList list = new ArrayList<>(); - int len = str.length(); - int separatorLen = separator.length(); - int start = 0; - int i = 0; - while (i < len) { - i = StrUtil.indexOf(str, separator, start, ignoreCase); - if (i > -1) { - addToList(list, str.substring(start, i), isTrim, ignoreEmpty); - start = i + separatorLen; - - //检查是否超出范围(最大允许limit-1个,剩下一个留给末尾字符串) - if (limit > 0 && list.size() > limit - 2) { - break; - } - } else { - break; - } - } - return addToList(list, str.substring(start, len), isTrim, ignoreEmpty); - } - - /** - * 切分字符串为字符串数组 - * - * @param str 被切分的字符串 - * @param separator 分隔符字符 - * @param limit 限制分片数 - * @param isTrim 是否去除切分字符串后每个元素两边的空格 - * @param ignoreEmpty 是否忽略空串 - * @return 切分后的集合 - * @since 3.0.8 - */ - public static String[] splitToArray(String str, String separator, int limit, boolean isTrim, boolean ignoreEmpty) { - return toArray(split(str, separator, limit, isTrim, ignoreEmpty)); - } - - //---------------------------------------------------------------------------------------------- Split by Whitespace - - /** - * 使用空白符切分字符串
- * 切分后的字符串两边不包含空白符,空串或空白符串并不做为元素之一 - * - * @param str 被切分的字符串 - * @param limit 限制分片数 - * @return 切分后的集合 - * @since 3.0.8 - */ - public static List split(String str, int limit) { - if (StrUtil.isEmpty(str)) { - return new ArrayList<>(0); - } - if (limit == 1) { - return addToList(new ArrayList<>(1), str, true, true); - } - - final ArrayList list = new ArrayList<>(); - int len = str.length(); - int start = 0;//切分后每个部分的起始 - for (int i = 0; i < len; i++) { - if (CharUtil.isBlankChar(str.charAt(i))) { - addToList(list, str.substring(start, i), true, true); - start = i + 1;//i+1同时将start与i保持一致 - - //检查是否超出范围(最大允许limit-1个,剩下一个留给末尾字符串) - if (limit > 0 && list.size() > limit - 2) { - break; - } - } - } - return addToList(list, str.substring(start, len), true, true);//收尾 - } - - /** - * 切分字符串为字符串数组 - * - * @param str 被切分的字符串 - * @param limit 限制分片数 - * @return 切分后的集合 - * @since 3.0.8 - */ - public static String[] splitToArray(String str, int limit) { - return toArray(split(str, limit)); - } - - //---------------------------------------------------------------------------------------------- Split by regex - - /** - * 通过正则切分字符串 - * - * @param str 字符串 - * @param separatorRegex 分隔符正则 - * @param limit 限制分片数 - * @param isTrim 是否去除切分字符串后每个元素两边的空格 - * @param ignoreEmpty 是否忽略空串 - * @return 切分后的集合 - * @since 3.0.8 - */ - public static List splitByRegex(String str, String separatorRegex, int limit, boolean isTrim, boolean ignoreEmpty) { - final Pattern pattern = PatternPool.get(separatorRegex); - return split(str, pattern, limit, isTrim, ignoreEmpty); - } - - /** - * 通过正则切分字符串 - * - * @param str 字符串 - * @param separatorPattern 分隔符正则{@link Pattern} - * @param limit 限制分片数 - * @param isTrim 是否去除切分字符串后每个元素两边的空格 - * @param ignoreEmpty 是否忽略空串 - * @return 切分后的集合 - * @since 3.0.8 - */ - public static List split(String str, Pattern separatorPattern, int limit, boolean isTrim, boolean ignoreEmpty) { - if (StrUtil.isEmpty(str)) { - return new ArrayList<>(0); - } - if (limit == 1) { - return addToList(new ArrayList<>(1), str, isTrim, ignoreEmpty); - } - - if (null == separatorPattern) {//分隔符为空时按照空白符切分 - return split(str, limit); - } - - final Matcher matcher = separatorPattern.matcher(str); - final ArrayList list = new ArrayList<>(); - int len = str.length(); - int start = 0; - while (matcher.find()) { - addToList(list, str.substring(start, matcher.start()), isTrim, ignoreEmpty); - start = matcher.end(); - - //检查是否超出范围(最大允许limit-1个,剩下一个留给末尾字符串) - if (limit > 0 && list.size() > limit - 2) { - break; - } - } - return addToList(list, str.substring(start, len), isTrim, ignoreEmpty); - } - - /** - * 通过正则切分字符串为字符串数组 - * - * @param str 被切分的字符串 - * @param separatorPattern 分隔符正则{@link Pattern} - * @param limit 限制分片数 - * @param isTrim 是否去除切分字符串后每个元素两边的空格 - * @param ignoreEmpty 是否忽略空串 - * @return 切分后的集合 - * @since 3.0.8 - */ - public static String[] splitToArray(String str, Pattern separatorPattern, int limit, boolean isTrim, boolean ignoreEmpty) { - return toArray(split(str, separatorPattern, limit, isTrim, ignoreEmpty)); - } - - //---------------------------------------------------------------------------------------------- Split by length - - /** - * 根据给定长度,将给定字符串截取为多个部分 - * - * @param str 字符串 - * @param len 每一个小节的长度 - * @return 截取后的字符串数组 - */ - public static String[] splitByLength(String str, int len) { - int partCount = str.length() / len; - int lastPartCount = str.length() % len; - int fixPart = 0; - if (lastPartCount != 0) { - fixPart = 1; - } - - final String[] strs = new String[partCount + fixPart]; - for (int i = 0; i < partCount + fixPart; i++) { - if (i == partCount + fixPart - 1 && lastPartCount != 0) { - strs[i] = str.substring(i * len, i * len + lastPartCount); - } else { - strs[i] = str.substring(i * len, i * len + len); - } - } - return strs; - } - - //---------------------------------------------------------------------------------------------------------- Private method start - - /** - * 将字符串加入List中 - * - * @param list 列表 - * @param part 被加入的部分 - * @param isTrim 是否去除两端空白符 - * @param ignoreEmpty 是否略过空字符串(空字符串不做为一个元素) - * @return 列表 - */ - private static List addToList(List list, String part, boolean isTrim, boolean ignoreEmpty) { - if (isTrim) { - part = StrUtil.trim(part); - } - if (false == ignoreEmpty || false == part.isEmpty()) { - list.add(part); - } - return list; - } - - /** - * List转Array - * - * @param list List - * @return Array - */ - private static String[] toArray(List list) { - return list.toArray(new String[0]); - } - //---------------------------------------------------------------------------------------------------------- Private method end +@Deprecated +public class StrSpliter extends StrSplitter{ } diff --git a/hutool-core/src/main/java/cn/hutool/core/text/StrSplitter.java b/hutool-core/src/main/java/cn/hutool/core/text/StrSplitter.java new file mode 100644 index 000000000..295361c33 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/text/StrSplitter.java @@ -0,0 +1,521 @@ +package cn.hutool.core.text; + +import cn.hutool.core.lang.PatternPool; +import cn.hutool.core.util.CharUtil; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.StrUtil; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 字符串切分器 + * + * @author Looly + * @since 5.7.0 + */ +public class StrSplitter { + + //---------------------------------------------------------------------------------------------- Split by char + + /** + * 切分字符串路径,仅支持Unix分界符:/ + * + * @param str 被切分的字符串 + * @return 切分后的集合 + * @since 3.0.8 + */ + public static List splitPath(String str) { + return splitPath(str, 0); + } + + /** + * 切分字符串路径,仅支持Unix分界符:/ + * + * @param str 被切分的字符串 + * @return 切分后的集合 + * @since 3.0.8 + */ + public static String[] splitPathToArray(String str) { + return toArray(splitPath(str)); + } + + /** + * 切分字符串路径,仅支持Unix分界符:/ + * + * @param str 被切分的字符串 + * @param limit 限制分片数 + * @return 切分后的集合 + * @since 3.0.8 + */ + public static List splitPath(String str, int limit) { + return split(str, StrUtil.C_SLASH, limit, true, true); + } + + /** + * 切分字符串路径,仅支持Unix分界符:/ + * + * @param str 被切分的字符串 + * @param limit 限制分片数 + * @return 切分后的集合 + * @since 3.0.8 + */ + public static String[] splitPathToArray(String str, int limit) { + return toArray(splitPath(str, limit)); + } + + /** + * 切分字符串 + * + * @param str 被切分的字符串 + * @param separator 分隔符字符 + * @param ignoreEmpty 是否忽略空串 + * @return 切分后的集合 + * @since 3.2.1 + */ + public static List splitTrim(String str, char separator, boolean ignoreEmpty) { + return split(str, separator, 0, true, ignoreEmpty); + } + + /** + * 切分字符串 + * + * @param str 被切分的字符串 + * @param separator 分隔符字符 + * @param isTrim 是否去除切分字符串后每个元素两边的空格 + * @param ignoreEmpty 是否忽略空串 + * @return 切分后的集合 + * @since 3.0.8 + */ + public static List split(String str, char separator, boolean isTrim, boolean ignoreEmpty) { + return split(str, separator, 0, isTrim, ignoreEmpty); + } + + /** + * 切分字符串,大小写敏感,去除每个元素两边空白符 + * + * @param str 被切分的字符串 + * @param separator 分隔符字符 + * @param limit 限制分片数,-1不限制 + * @param ignoreEmpty 是否忽略空串 + * @return 切分后的集合 + * @since 3.0.8 + */ + public static List splitTrim(String str, char separator, int limit, boolean ignoreEmpty) { + return split(str, separator, limit, true, ignoreEmpty, false); + } + + /** + * 切分字符串,大小写敏感 + * + * @param str 被切分的字符串 + * @param separator 分隔符字符 + * @param limit 限制分片数,-1不限制 + * @param isTrim 是否去除切分字符串后每个元素两边的空格 + * @param ignoreEmpty 是否忽略空串 + * @return 切分后的集合 + * @since 3.0.8 + */ + public static List split(String str, char separator, int limit, boolean isTrim, boolean ignoreEmpty) { + return split(str, separator, limit, isTrim, ignoreEmpty, false); + } + + /** + * 切分字符串,忽略大小写 + * + * @param str 被切分的字符串 + * @param separator 分隔符字符 + * @param limit 限制分片数,-1不限制 + * @param isTrim 是否去除切分字符串后每个元素两边的空格 + * @param ignoreEmpty 是否忽略空串 + * @return 切分后的集合 + * @since 3.2.1 + */ + public static List splitIgnoreCase(String str, char separator, int limit, boolean isTrim, boolean ignoreEmpty) { + return split(str, separator, limit, isTrim, ignoreEmpty, true); + } + + /** + * 切分字符串 + * + * @param str 被切分的字符串 + * @param separator 分隔符字符 + * @param limit 限制分片数,-1不限制 + * @param isTrim 是否去除切分字符串后每个元素两边的空格 + * @param ignoreEmpty 是否忽略空串 + * @param ignoreCase 是否忽略大小写 + * @return 切分后的集合 + * @since 3.2.1 + */ + public static List split(String str, char separator, int limit, boolean isTrim, boolean ignoreEmpty, boolean ignoreCase) { + if (StrUtil.isEmpty(str)) { + return new ArrayList<>(0); + } + if (limit == 1) { + return addToList(new ArrayList<>(1), str, isTrim, ignoreEmpty); + } + + final ArrayList list = new ArrayList<>(limit > 0 ? limit : 16); + int len = str.length(); + int start = 0;//切分后每个部分的起始 + for (int i = 0; i < len; i++) { + if (NumberUtil.equals(separator, str.charAt(i), ignoreCase)) { + addToList(list, str.substring(start, i), isTrim, ignoreEmpty); + start = i + 1;//i+1同时将start与i保持一致 + + //检查是否超出范围(最大允许limit-1个,剩下一个留给末尾字符串) + if (limit > 0 && list.size() > limit - 2) { + break; + } + } + } + return addToList(list, str.substring(start, len), isTrim, ignoreEmpty);//收尾 + } + + /** + * 切分字符串为字符串数组 + * + * @param str 被切分的字符串 + * @param separator 分隔符字符 + * @param limit 限制分片数 + * @param isTrim 是否去除切分字符串后每个元素两边的空格 + * @param ignoreEmpty 是否忽略空串 + * @return 切分后的集合 + * @since 3.0.8 + */ + public static String[] splitToArray(String str, char separator, int limit, boolean isTrim, boolean ignoreEmpty) { + return toArray(split(str, separator, limit, isTrim, ignoreEmpty)); + } + + //---------------------------------------------------------------------------------------------- Split by String + + /** + * 切分字符串,不忽略大小写 + * + * @param str 被切分的字符串 + * @param separator 分隔符字符串 + * @param isTrim 是否去除切分字符串后每个元素两边的空格 + * @param ignoreEmpty 是否忽略空串 + * @return 切分后的集合 + * @since 3.0.8 + */ + public static List split(String str, String separator, boolean isTrim, boolean ignoreEmpty) { + return split(str, separator, -1, isTrim, ignoreEmpty, false); + } + + /** + * 切分字符串,去除每个元素两边空格,忽略大小写 + * + * @param str 被切分的字符串 + * @param separator 分隔符字符串 + * @param ignoreEmpty 是否忽略空串 + * @return 切分后的集合 + * @since 3.2.1 + */ + public static List splitTrim(String str, String separator, boolean ignoreEmpty) { + return split(str, separator, true, ignoreEmpty); + } + + /** + * 切分字符串,不忽略大小写 + * + * @param str 被切分的字符串 + * @param separator 分隔符字符串 + * @param limit 限制分片数 + * @param isTrim 是否去除切分字符串后每个元素两边的空格 + * @param ignoreEmpty 是否忽略空串 + * @return 切分后的集合 + * @since 3.0.8 + */ + public static List split(String str, String separator, int limit, boolean isTrim, boolean ignoreEmpty) { + return split(str, separator, limit, isTrim, ignoreEmpty, false); + } + + /** + * 切分字符串,去除每个元素两边空格,忽略大小写 + * + * @param str 被切分的字符串 + * @param separator 分隔符字符串 + * @param limit 限制分片数 + * @param ignoreEmpty 是否忽略空串 + * @return 切分后的集合 + * @since 3.2.1 + */ + public static List splitTrim(String str, String separator, int limit, boolean ignoreEmpty) { + return split(str, separator, limit, true, ignoreEmpty); + } + + /** + * 切分字符串,忽略大小写 + * + * @param str 被切分的字符串 + * @param separator 分隔符字符串 + * @param limit 限制分片数 + * @param isTrim 是否去除切分字符串后每个元素两边的空格 + * @param ignoreEmpty 是否忽略空串 + * @return 切分后的集合 + * @since 3.2.1 + */ + public static List splitIgnoreCase(String str, String separator, int limit, boolean isTrim, boolean ignoreEmpty) { + return split(str, separator, limit, isTrim, ignoreEmpty, true); + } + + /** + * 切分字符串,去除每个元素两边空格,忽略大小写 + * + * @param str 被切分的字符串 + * @param separator 分隔符字符串 + * @param limit 限制分片数 + * @param ignoreEmpty 是否忽略空串 + * @return 切分后的集合 + * @since 3.2.1 + */ + public static List splitTrimIgnoreCase(String str, String separator, int limit, boolean ignoreEmpty) { + return split(str, separator, limit, true, ignoreEmpty, true); + } + + /** + * 切分字符串 + * + * @param str 被切分的字符串 + * @param separator 分隔符字符串 + * @param limit 限制分片数 + * @param isTrim 是否去除切分字符串后每个元素两边的空格 + * @param ignoreEmpty 是否忽略空串 + * @param ignoreCase 是否忽略大小写 + * @return 切分后的集合 + * @since 3.2.1 + */ + public static List split(String str, String separator, int limit, boolean isTrim, boolean ignoreEmpty, boolean ignoreCase) { + if (StrUtil.isEmpty(str)) { + return new ArrayList<>(0); + } + if (limit == 1) { + return addToList(new ArrayList<>(1), str, isTrim, ignoreEmpty); + } + + if (StrUtil.isEmpty(separator)) {//分隔符为空时按照空白符切分 + return split(str, limit); + } else if (separator.length() == 1) {//分隔符只有一个字符长度时按照单分隔符切分 + return split(str, separator.charAt(0), limit, isTrim, ignoreEmpty, ignoreCase); + } + + final ArrayList list = new ArrayList<>(); + int len = str.length(); + int separatorLen = separator.length(); + int start = 0; + int i = 0; + while (i < len) { + i = StrUtil.indexOf(str, separator, start, ignoreCase); + if (i > -1) { + addToList(list, str.substring(start, i), isTrim, ignoreEmpty); + start = i + separatorLen; + + //检查是否超出范围(最大允许limit-1个,剩下一个留给末尾字符串) + if (limit > 0 && list.size() > limit - 2) { + break; + } + } else { + break; + } + } + return addToList(list, str.substring(start, len), isTrim, ignoreEmpty); + } + + /** + * 切分字符串为字符串数组 + * + * @param str 被切分的字符串 + * @param separator 分隔符字符 + * @param limit 限制分片数 + * @param isTrim 是否去除切分字符串后每个元素两边的空格 + * @param ignoreEmpty 是否忽略空串 + * @return 切分后的集合 + * @since 3.0.8 + */ + public static String[] splitToArray(String str, String separator, int limit, boolean isTrim, boolean ignoreEmpty) { + return toArray(split(str, separator, limit, isTrim, ignoreEmpty)); + } + + //---------------------------------------------------------------------------------------------- Split by Whitespace + + /** + * 使用空白符切分字符串
+ * 切分后的字符串两边不包含空白符,空串或空白符串并不做为元素之一 + * + * @param str 被切分的字符串 + * @param limit 限制分片数 + * @return 切分后的集合 + * @since 3.0.8 + */ + public static List split(String str, int limit) { + if (StrUtil.isEmpty(str)) { + return new ArrayList<>(0); + } + if (limit == 1) { + return addToList(new ArrayList<>(1), str, true, true); + } + + final ArrayList list = new ArrayList<>(); + int len = str.length(); + int start = 0;//切分后每个部分的起始 + for (int i = 0; i < len; i++) { + if (CharUtil.isBlankChar(str.charAt(i))) { + addToList(list, str.substring(start, i), true, true); + start = i + 1;//i+1同时将start与i保持一致 + + //检查是否超出范围(最大允许limit-1个,剩下一个留给末尾字符串) + if (limit > 0 && list.size() > limit - 2) { + break; + } + } + } + return addToList(list, str.substring(start, len), true, true);//收尾 + } + + /** + * 切分字符串为字符串数组 + * + * @param str 被切分的字符串 + * @param limit 限制分片数 + * @return 切分后的集合 + * @since 3.0.8 + */ + public static String[] splitToArray(String str, int limit) { + return toArray(split(str, limit)); + } + + //---------------------------------------------------------------------------------------------- Split by regex + + /** + * 通过正则切分字符串 + * + * @param str 字符串 + * @param separatorRegex 分隔符正则 + * @param limit 限制分片数 + * @param isTrim 是否去除切分字符串后每个元素两边的空格 + * @param ignoreEmpty 是否忽略空串 + * @return 切分后的集合 + * @since 3.0.8 + */ + public static List splitByRegex(String str, String separatorRegex, int limit, boolean isTrim, boolean ignoreEmpty) { + final Pattern pattern = PatternPool.get(separatorRegex); + return split(str, pattern, limit, isTrim, ignoreEmpty); + } + + /** + * 通过正则切分字符串 + * + * @param str 字符串 + * @param separatorPattern 分隔符正则{@link Pattern} + * @param limit 限制分片数 + * @param isTrim 是否去除切分字符串后每个元素两边的空格 + * @param ignoreEmpty 是否忽略空串 + * @return 切分后的集合 + * @since 3.0.8 + */ + public static List split(String str, Pattern separatorPattern, int limit, boolean isTrim, boolean ignoreEmpty) { + if (StrUtil.isEmpty(str)) { + return new ArrayList<>(0); + } + if (limit == 1) { + return addToList(new ArrayList<>(1), str, isTrim, ignoreEmpty); + } + + if (null == separatorPattern) {//分隔符为空时按照空白符切分 + return split(str, limit); + } + + final Matcher matcher = separatorPattern.matcher(str); + final ArrayList list = new ArrayList<>(); + int len = str.length(); + int start = 0; + while (matcher.find()) { + addToList(list, str.substring(start, matcher.start()), isTrim, ignoreEmpty); + start = matcher.end(); + + //检查是否超出范围(最大允许limit-1个,剩下一个留给末尾字符串) + if (limit > 0 && list.size() > limit - 2) { + break; + } + } + return addToList(list, str.substring(start, len), isTrim, ignoreEmpty); + } + + /** + * 通过正则切分字符串为字符串数组 + * + * @param str 被切分的字符串 + * @param separatorPattern 分隔符正则{@link Pattern} + * @param limit 限制分片数 + * @param isTrim 是否去除切分字符串后每个元素两边的空格 + * @param ignoreEmpty 是否忽略空串 + * @return 切分后的集合 + * @since 3.0.8 + */ + public static String[] splitToArray(String str, Pattern separatorPattern, int limit, boolean isTrim, boolean ignoreEmpty) { + return toArray(split(str, separatorPattern, limit, isTrim, ignoreEmpty)); + } + + //---------------------------------------------------------------------------------------------- Split by length + + /** + * 根据给定长度,将给定字符串截取为多个部分 + * + * @param str 字符串 + * @param len 每一个小节的长度 + * @return 截取后的字符串数组 + */ + public static String[] splitByLength(String str, int len) { + int partCount = str.length() / len; + int lastPartCount = str.length() % len; + int fixPart = 0; + if (lastPartCount != 0) { + fixPart = 1; + } + + final String[] strs = new String[partCount + fixPart]; + for (int i = 0; i < partCount + fixPart; i++) { + if (i == partCount + fixPart - 1 && lastPartCount != 0) { + strs[i] = str.substring(i * len, i * len + lastPartCount); + } else { + strs[i] = str.substring(i * len, i * len + len); + } + } + return strs; + } + + //---------------------------------------------------------------------------------------------------------- Private method start + + /** + * 将字符串加入List中 + * + * @param list 列表 + * @param part 被加入的部分 + * @param isTrim 是否去除两端空白符 + * @param ignoreEmpty 是否略过空字符串(空字符串不做为一个元素) + * @return 列表 + */ + private static List addToList(List list, String part, boolean isTrim, boolean ignoreEmpty) { + if (isTrim) { + part = StrUtil.trim(part); + } + if (false == ignoreEmpty || false == part.isEmpty()) { + list.add(part); + } + return list; + } + + /** + * List转Array + * + * @param list List + * @return Array + */ + private static String[] toArray(List list) { + return list.toArray(new String[0]); + } + //---------------------------------------------------------------------------------------------------------- Private method end +} diff --git a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java index ba1504213..80d1bfc6c 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java @@ -1008,6 +1008,7 @@ public class NumberUtil { * @return 格式化后的值 */ public static String decimalFormat(String pattern, double value) { + Assert.isTrue(isValid(value), "value is NaN or Infinite!"); return new DecimalFormat(pattern).format(value); } @@ -1078,6 +1079,9 @@ public class NumberUtil { * @since 5.6.5 */ public static String decimalFormat(String pattern, Object value, RoundingMode roundingMode) { + if(value instanceof Number){ + Assert.isTrue(isValidNumber((Number) value), "value is NaN or Infinite!"); + } final DecimalFormat decimalFormat = new DecimalFormat(pattern); if(null != roundingMode){ decimalFormat.setRoundingMode(roundingMode); @@ -2660,6 +2664,30 @@ public class NumberUtil { return true; } + /** + * 检查是否为有效的数字
+ * 检查double否为无限大,或者Not a Number(NaN)
+ * + * @param number 被检查double + * @return 检查结果 + * @since 5.7.0 + */ + public static boolean isValid(double number) { + return false == (Double.isNaN(number) || Double.isInfinite(number)); + } + + /** + * 检查是否为有效的数字
+ * 检查double否为无限大,或者Not a Number(NaN)
+ * + * @param number 被检查double + * @return 检查结果 + * @since 5.7.0 + */ + public static boolean isValid(float number) { + return false == (Float.isNaN(number) || Float.isInfinite(number)); + } + // ------------------------------------------------------------------------------------------- Private method start private static int mathSubNode(int selectNum, int minNum) { if (selectNum == minNum) { diff --git a/hutool-core/src/test/java/cn/hutool/core/img/ImgUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/img/ImgUtilTest.java index 7cd4930cb..839b3defc 100644 --- a/hutool-core/src/test/java/cn/hutool/core/img/ImgUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/img/ImgUtilTest.java @@ -145,4 +145,5 @@ public class ImgUtilTest { String mainColor = ImgUtil.getMainColor(read, new int[]{64,84,116}); System.out.println(mainColor); } + } diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/StrSpliterTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/StrSpliterTest.java index bca9673a3..072f391ae 100644 --- a/hutool-core/src/test/java/cn/hutool/core/lang/StrSpliterTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/lang/StrSpliterTest.java @@ -5,43 +5,43 @@ import java.util.List; import org.junit.Assert; import org.junit.Test; -import cn.hutool.core.text.StrSpliter; +import cn.hutool.core.text.StrSplitter; /** - * {@link StrSpliter} 单元测试 + * {@link StrSplitter} 单元测试 * @author Looly * */ public class StrSpliterTest { - + @Test public void splitByCharTest(){ String str1 = "a, ,efedsfs, ddf"; - List split = StrSpliter.split(str1, ',', 0, true, true); + List split = StrSplitter.split(str1, ',', 0, true, true); Assert.assertEquals("ddf", split.get(2)); Assert.assertEquals(3, split.size()); } - + @Test public void splitByStrTest(){ String str1 = "aabbccaaddaaee"; - List split = StrSpliter.split(str1, "aa", 0, true, true); + List split = StrSplitter.split(str1, "aa", 0, true, true); Assert.assertEquals("ee", split.get(2)); Assert.assertEquals(3, split.size()); } - + @Test public void splitByBlankTest(){ String str1 = "aa bbccaa ddaaee"; - List split = StrSpliter.split(str1, 0); + List split = StrSplitter.split(str1, 0); Assert.assertEquals("ddaaee", split.get(2)); Assert.assertEquals(3, split.size()); } - + @Test public void splitPathTest(){ String str1 = "/use/local/bin"; - List split = StrSpliter.splitPath(str1, 0); + List split = StrSplitter.splitPath(str1, 0); Assert.assertEquals("bin", split.get(2)); Assert.assertEquals(3, split.size()); } diff --git a/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java index 98460b9b4..dc2186d93 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java @@ -1,6 +1,7 @@ package cn.hutool.core.util; import cn.hutool.core.convert.Convert; +import cn.hutool.core.lang.Console; import org.junit.Assert; import org.junit.Test; @@ -161,6 +162,23 @@ public class NumberUtilTest { Assert.assertEquals("299,792,458", format); } + @Test(expected = IllegalArgumentException.class) + public void decimalFormatNaNTest(){ + Double a = 0D; + Double b = 0D; + + Double c = a / b; + Console.log(NumberUtil.decimalFormat("#%", c)); + } + + @Test(expected = IllegalArgumentException.class) + public void decimalFormatNaNTest2(){ + Double a = 0D; + Double b = 0D; + + Console.log(NumberUtil.decimalFormat("#%", a / b)); + } + @Test public void decimalFormatDoubleTest() { Double c = 467.8101; diff --git a/hutool-db/src/main/java/cn/hutool/db/sql/Condition.java b/hutool-db/src/main/java/cn/hutool/db/sql/Condition.java index e5ecb0fc7..a53388663 100644 --- a/hutool-db/src/main/java/cn/hutool/db/sql/Condition.java +++ b/hutool-db/src/main/java/cn/hutool/db/sql/Condition.java @@ -2,7 +2,7 @@ package cn.hutool.db.sql; import cn.hutool.core.clone.CloneSupport; import cn.hutool.core.convert.Convert; -import cn.hutool.core.text.StrSpliter; +import cn.hutool.core.text.StrSplitter; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.CharUtil; import cn.hutool.core.util.NumberUtil; @@ -488,7 +488,7 @@ public class Condition extends CloneSupport { // 处理BETWEEN x AND y if (OPERATOR_BETWEEN.equals(firstPart)) { - final List betweenValueStrs = StrSpliter.splitTrimIgnoreCase(strs.get(1), LogicalOperator.AND.toString(), 2, true); + final List betweenValueStrs = StrSplitter.splitTrimIgnoreCase(strs.get(1), LogicalOperator.AND.toString(), 2, true); if (betweenValueStrs.size() < 2) { // 必须满足a AND b格式,不满足被当作普通值 return;