From 6a04ef4a3a0b2c62729be738ae6edafb31b84754 Mon Sep 17 00:00:00 2001 From: Looly Date: Sat, 22 Apr 2023 21:53:58 +0800 Subject: [PATCH] fix code --- .../hutool/core/func/LambdaFactory.java | 23 +- .../dromara/hutool/core/func/LambdaUtil.java | 29 +- .../hutool/core/math/NumberParser.java | 42 +++ .../dromara/hutool/core/math/NumberUtil.java | 268 +----------------- .../hutool/core/math/NumberValidator.java | 251 ++++++++++++++++ .../hutool/core/text/CharSequenceUtil.java | 2 +- .../{StrChecker.java => StrValidator.java} | 2 +- .../text/placeholder/PlaceholderParser.java | 10 +- .../{lang => }/func/FunctionPoolTest.java | 14 +- .../{lang => }/func/LambdaFactoryTest.java | 16 +- .../core/{lang => }/func/LambdaUtilTest.java | 50 +++- .../{lang => }/func/PredicateUtilTest.java | 14 +- 12 files changed, 422 insertions(+), 299 deletions(-) create mode 100644 hutool-core/src/main/java/org/dromara/hutool/core/math/NumberValidator.java rename hutool-core/src/main/java/org/dromara/hutool/core/text/{StrChecker.java => StrValidator.java} (99%) rename hutool-core/src/test/java/org/dromara/hutool/core/{lang => }/func/FunctionPoolTest.java (62%) rename hutool-core/src/test/java/org/dromara/hutool/core/{lang => }/func/LambdaFactoryTest.java (96%) rename hutool-core/src/test/java/org/dromara/hutool/core/{lang => }/func/LambdaUtilTest.java (87%) rename hutool-core/src/test/java/org/dromara/hutool/core/{lang => }/func/PredicateUtilTest.java (68%) diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/func/LambdaFactory.java b/hutool-core/src/main/java/org/dromara/hutool/core/func/LambdaFactory.java index 40c94b76d..971ae6ad4 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/func/LambdaFactory.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/func/LambdaFactory.java @@ -95,10 +95,7 @@ public class LambdaFactory { ReflectUtil.setAccessible(executable); // 获取Lambda函数 - final Method[] abstractMethods = MethodUtil.getPublicMethods(funcType, ModifierUtil::isAbstract); - Assert.equals(abstractMethods.length, 1, "不支持非函数式接口"); - - final Method invokeMethod = abstractMethods[0]; + final Method invokeMethod = LambdaUtil.getInvokeMethod(funcType); try { return (F) metaFactory(funcType, invokeMethod, executable) .getTarget().invoke(); @@ -110,20 +107,24 @@ public class LambdaFactory { /** * 通过Lambda函数代理方法或构造 * - * @param funcType 函数类型 - * @param invokeMethod 函数执行的方法 - * @param executable 被代理的方法或构造 + * @param funcType 函数类型 + * @param funcMethod 函数执行的方法 + * @param executable 被代理的方法或构造 * @return {@link CallSite} * @throws LambdaConversionException 权限等异常 */ - private static CallSite metaFactory(final Class funcType, final Method invokeMethod, + private static CallSite metaFactory(final Class funcType, final Method funcMethod, final Executable executable) throws LambdaConversionException { + // 查找上下文与调用者的访问权限 final MethodHandles.Lookup caller = LookupUtil.lookup(executable.getDeclaringClass()); - final String invokeName = invokeMethod.getName(); + // 要实现的方法的名字 + final String invokeName = funcMethod.getName(); + // 调用点期望的方法参数的类型和返回值的类型(方法signature) final MethodType invokedType = MethodType.methodType(funcType); - final Class[] paramTypes = invokeMethod.getParameterTypes(); - final MethodType samMethodType = MethodType.methodType(invokeMethod.getReturnType(), paramTypes); + final Class[] paramTypes = funcMethod.getParameterTypes(); + // 函数对象将要实现的接口方法类型 + final MethodType samMethodType = MethodType.methodType(funcMethod.getReturnType(), paramTypes); if (ClassUtil.isSerializable(funcType)) { return LambdaMetafactory.altMetafactory( diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/func/LambdaUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/func/LambdaUtil.java index f6154e1f9..f94600fb8 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/func/LambdaUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/func/LambdaUtil.java @@ -15,9 +15,11 @@ package org.dromara.hutool.core.func; import org.dromara.hutool.core.bean.BeanUtil; import org.dromara.hutool.core.classloader.ClassLoaderUtil; import org.dromara.hutool.core.exceptions.HutoolException; +import org.dromara.hutool.core.lang.Assert; import org.dromara.hutool.core.lang.Opt; import org.dromara.hutool.core.map.WeakConcurrentMap; import org.dromara.hutool.core.reflect.MethodUtil; +import org.dromara.hutool.core.reflect.ModifierUtil; import org.dromara.hutool.core.reflect.ReflectUtil; import java.io.Serializable; @@ -76,9 +78,9 @@ public class LambdaUtil { public static Class getRealClass(final T func) { final LambdaInfo lambdaInfo = resolve(func); return (Class) Opt.of(lambdaInfo) - .map(LambdaInfo::getInstantiatedMethodParameterTypes) - .filter(types -> types.length != 0).map(types -> types[types.length - 1]) - .orElseGet(lambdaInfo::getClazz); + .map(LambdaInfo::getInstantiatedMethodParameterTypes) + .filter(types -> types.length != 0).map(types -> types[types.length - 1]) + .orElseGet(lambdaInfo::getClazz); } /** @@ -104,7 +106,7 @@ public class LambdaUtil { final Method[] methods = MethodUtil.getMethods(implClass); for (final Method method : methods) { if (method.getName().equals(methodName) - && ReflectUtil.getDescriptor(method).equals(serializedLambda.getImplMethodSignature())) { + && ReflectUtil.getDescriptor(method).equals(serializedLambda.getImplMethodSignature())) { return new LambdaInfo(method, serializedLambda); } } @@ -181,7 +183,7 @@ public class LambdaUtil { @SuppressWarnings("unchecked") public static BiConsumer buildSetter(final Method setMethod) { final Class returnType = setMethod.getReturnType(); - if(Void.TYPE == returnType){ + if (Void.TYPE == returnType) { return LambdaFactory.build(BiConsumer.class, setMethod); } @@ -261,7 +263,22 @@ public class LambdaUtil { return (t) -> biConsumer.accept(t, param); } - //region Private methods + /** + * 获取函数的执行方法 + * + * @param funcType 函数接口类 + * @return {@link Method} + * @since 6.0.0 + */ + public static Method getInvokeMethod(final Class funcType) { + // 获取Lambda函数 + final Method[] abstractMethods = MethodUtil.getPublicMethods(funcType, ModifierUtil::isAbstract); + Assert.equals(abstractMethods.length, 1, "Not a function class: " + funcType.getName()); + + return abstractMethods[0]; + } + + //region ----- Private methods /** * 解析lambda表达式,没加缓存 diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/math/NumberParser.java b/hutool-core/src/main/java/org/dromara/hutool/core/math/NumberParser.java index 0c5af9d8e..731ec5461 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/math/NumberParser.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/math/NumberParser.java @@ -14,6 +14,7 @@ package org.dromara.hutool.core.math; import org.dromara.hutool.core.text.StrUtil; +import java.math.BigInteger; import java.text.DecimalFormat; import java.text.NumberFormat; import java.text.ParseException; @@ -205,6 +206,47 @@ public class NumberParser { } } + /** + * 解析为{@link BigInteger},支持16进制、10进制和8进制,如果传入空白串返回null
+ * from Apache Common Lang + * + * @param str 数字字符串 + * @return {@link BigInteger} + */ + public BigInteger parseBigInteger(String str) { + str = StrUtil.trimToNull(str); + if (null == str) { + return null; + } + + int pos = 0; // 数字字符串位置 + int radix = 10; + boolean negate = false; // 负数与否 + if (str.startsWith("-")) { + negate = true; + pos = 1; + } + if (str.startsWith("0x", pos) || str.startsWith("0X", pos)) { + // hex + radix = 16; + pos += 2; + } else if (str.startsWith("#", pos)) { + // alternative hex (allowed by Long/Integer) + radix = 16; + pos++; + } else if (str.startsWith("0", pos) && str.length() > pos + 1) { + // octal; so long as there are additional digits + radix = 8; + pos++; + } // default is to treat as decimal + + if (pos > 0) { + str = str.substring(pos); + } + final BigInteger value = new BigInteger(str, radix); + return negate ? value.negate() : value; + } + /** * 将指定字符串转换为{@link Number} 对象
* 此方法不支持科学计数法 diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/math/NumberUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/math/NumberUtil.java index 45fdab884..51cc720ea 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/math/NumberUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/math/NumberUtil.java @@ -16,7 +16,6 @@ import org.dromara.hutool.core.array.ArrayUtil; import org.dromara.hutool.core.comparator.CompareUtil; import org.dromara.hutool.core.lang.Assert; import org.dromara.hutool.core.text.StrUtil; -import org.dromara.hutool.core.util.CharUtil; import org.dromara.hutool.core.util.ObjUtil; import java.math.BigDecimal; @@ -50,7 +49,7 @@ import java.util.Objects; * * @author Looly */ -public class NumberUtil { +public class NumberUtil extends NumberValidator { /** * 默认除法运算精度 @@ -641,233 +640,6 @@ public class NumberUtil { } // endregion - // region ----- isXXX - - /** - * 是否为数字,支持包括: - * - *
-	 * 1、10进制
-	 * 2、16进制数字(0x开头)
-	 * 3、科学计数法形式(1234E3)
-	 * 4、类型标识形式(123D)
-	 * 5、正负数标识形式(+123、-234)
-	 * 6、八进制数字(0开头)
-	 * 
- * - * @param str 字符串值, 不可以含有任何空白字符 - * @return 是否为数字 - */ - public static boolean isNumber(final CharSequence str) { - if (StrUtil.isBlank(str)) { - return false; - } - final char[] chars = str.toString().toCharArray(); - int sz = chars.length; - boolean hasExp = false; - boolean hasDecPoint = false; - boolean allowSigns = false; - boolean foundDigit = false; - // deal with any possible sign up front - final int start = (chars[0] == '-' || chars[0] == '+') ? 1 : 0; - if (sz > start + 1 && chars[start] == '0' && !StrUtil.contains(str, CharUtil.DOT)) { // leading 0, skip if is a decimal number - if (chars[start + 1] == 'x' || chars[start + 1] == 'X') { // leading 0x/0X - int i = start + 2; - if (i == sz) { - return false; // str == "0x" - } - // checking hex (it can't be anything else) - for (; i < chars.length; i++) { - if ((chars[i] < '0' || chars[i] > '9') && (chars[i] < 'a' || chars[i] > 'f') && (chars[i] < 'A' || chars[i] > 'F')) { - return false; - } - } - return true; - } - if (Character.isDigit(chars[start + 1])) { - // leading 0, but not hex, must be octal - int i = start + 1; - for (; i < chars.length; i++) { - if (chars[i] < '0' || chars[i] > '7') { - return false; - } - } - return true; - } - } - sz--; // don't want to loop to the last char, check it afterwords - // for type qualifiers - int i = start; - // loop to the next to last char or to the last char if we need another digit to - // make a valid number (e.g. chars[0..5] = "1234E") - while (i < sz || (i < sz + 1 && allowSigns && !foundDigit)) { - if (chars[i] >= '0' && chars[i] <= '9') { - foundDigit = true; - allowSigns = false; - - } else if (chars[i] == '.') { - if (hasDecPoint || hasExp) { - // two decimal points or dec in exponent - return false; - } - hasDecPoint = true; - } else if (chars[i] == 'e' || chars[i] == 'E') { - // we've already taken care of hex. - if (hasExp) { - // two E's - return false; - } - if (!foundDigit) { - return false; - } - hasExp = true; - allowSigns = true; - } else if (chars[i] == '+' || chars[i] == '-') { - if (!allowSigns) { - return false; - } - allowSigns = false; - foundDigit = false; // we need a digit after the E - } else { - return false; - } - i++; - } - if (i < chars.length) { - if (chars[i] >= '0' && chars[i] <= '9') { - // no type qualifier, OK - return true; - } - if (chars[i] == 'e' || chars[i] == 'E') { - // can't have an E at the last byte - return false; - } - if (chars[i] == '.') { - if (hasDecPoint || hasExp) { - // two decimal points or dec in exponent - return false; - } - // single trailing decimal point after non-exponent is ok - return foundDigit; - } - if (!allowSigns && (chars[i] == 'd' || chars[i] == 'D' || chars[i] == 'f' || chars[i] == 'F')) { - return foundDigit; - } - if (chars[i] == 'l' || chars[i] == 'L') { - // not allowing L with an exponent or decimal point - return foundDigit && !hasExp && !hasDecPoint; - } - // last character is illegal - return false; - } - // allowSigns is true iff the val ends in 'E' - // found digit it to make sure weird stuff like '.' and '1E-' doesn't pass - return !allowSigns && foundDigit; - } - - /** - * 判断字符串是否是整数 - * - *

支持格式: - *

    - *
  1. 10进制, 不能包含前导零
  2. - *
  3. 8进制(以0开头)
  4. - *
  5. 16进制(以0x或者0X开头)
  6. - *
- * - * @param s 校验的字符串, 只能含有 正负号、数字字符 和 {@literal X/x} - * @return 是否为 {@link Integer}类型 - * @apiNote 6.0.0 支持8进制和16进制 - * @see Integer#decode(String) - */ - public static boolean isInteger(final String s) { - if (!isNumber(s)) { - return false; - } - try { - //noinspection ResultOfMethodCallIgnored - Integer.decode(s); - } catch (final NumberFormatException e) { - return false; - } - return true; - } - - /** - * 判断字符串是否是Long类型
- * - *

支持格式: - *

    - *
  1. 10进制, 不能包含前导零
  2. - *
  3. 8进制(以0开头)
  4. - *
  5. 16进制(以0x或者0X开头)
  6. - *
- * - * @param s 校验的字符串, 只能含有 正负号、数字字符、{@literal X/x} 和 后缀{@literal L/l} - * @return 是否为 {@link Long}类型 - * @apiNote 6.0.0 支持8进制和16进制数字 - * @since 4.0.0 - */ - public static boolean isLong(final String s) { - if (!isNumber(s)) { - return false; - } - final char lastChar = s.charAt(s.length() - 1); - if (lastChar == 'l' || lastChar == 'L') { - return true; - } - try { - //noinspection ResultOfMethodCallIgnored - Long.decode(s); - } catch (final NumberFormatException e) { - return false; - } - return true; - } - - /** - * 判断字符串是否是浮点数 - * - * @param s String - * @return 是否为 {@link Double}类型 - */ - public static boolean isDouble(final String s) { - if (StrUtil.isBlank(s)) { - return false; - } - try { - Double.parseDouble(s); - } catch (final NumberFormatException ignore) { - return false; - } - return s.contains("."); - } - - /** - * 是否是质数(素数)
- * 质数表的质数又称素数。指整数在一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数。 - * - * @param n 数字 - * @return 是否是质数 - */ - public static boolean isPrime(final int n) { - Assert.isTrue(n > 1, "The number must be > 1"); - if (n <= 3) { - return true; - } else if ((n & 1) == 0) { - // 快速排除偶数 - return false; - } - final int end = (int) Math.sqrt(n); - for (int i = 3; i <= end; i += 2) { - if (n % i == 0) { - return false; - } - } - return true; - } - // endregion - // region ----- range /** @@ -1252,42 +1024,12 @@ public class NumberUtil { * 创建{@link BigInteger},支持16进制、10进制和8进制,如果传入空白串返回null
* from Apache Common Lang * - * @param str 数字字符串 + * @param numberStr 数字字符串 * @return {@link BigInteger} - * @since 3.2.1 + * @since 6.0.0 */ - public static BigInteger newBigInteger(String str) { - str = StrUtil.trimToNull(str); - if (null == str) { - return null; - } - - int pos = 0; // 数字字符串位置 - int radix = 10; - boolean negate = false; // 负数与否 - if (str.startsWith("-")) { - negate = true; - pos = 1; - } - if (str.startsWith("0x", pos) || str.startsWith("0X", pos)) { - // hex - radix = 16; - pos += 2; - } else if (str.startsWith("#", pos)) { - // alternative hex (allowed by Long/Integer) - radix = 16; - pos++; - } else if (str.startsWith("0", pos) && str.length() > pos + 1) { - // octal; so long as there are additional digits - radix = 8; - pos++; - } // default is to treat as decimal - - if (pos > 0) { - str = str.substring(pos); - } - final BigInteger value = new BigInteger(str, radix); - return negate ? value.negate() : value; + public static BigInteger parseBigInteger(final String numberStr) { + return NumberParser.INSTANCE.parseBigInteger(numberStr); } /** diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/math/NumberValidator.java b/hutool-core/src/main/java/org/dromara/hutool/core/math/NumberValidator.java new file mode 100644 index 000000000..5a8ae6080 --- /dev/null +++ b/hutool-core/src/main/java/org/dromara/hutool/core/math/NumberValidator.java @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2023 looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package org.dromara.hutool.core.math; + +import org.dromara.hutool.core.lang.Assert; +import org.dromara.hutool.core.text.StrUtil; +import org.dromara.hutool.core.util.CharUtil; + +/** + * 数字检查器 + * + * @author looly + * @since 6.0.0 + */ +public class NumberValidator { + + /** + * 是否为数字,支持包括: + * + *
+	 * 1、10进制
+	 * 2、16进制数字(0x开头)
+	 * 3、科学计数法形式(1234E3)
+	 * 4、类型标识形式(123D)
+	 * 5、正负数标识形式(+123、-234)
+	 * 6、八进制数字(0开头)
+	 * 
+ * + * @param str 字符串值, 不可以含有任何空白字符 + * @return 是否为数字 + */ + public static boolean isNumber(final CharSequence str) { + if (StrUtil.isBlank(str)) { + return false; + } + final char[] chars = str.toString().toCharArray(); + int sz = chars.length; + boolean hasExp = false; + boolean hasDecPoint = false; + boolean allowSigns = false; + boolean foundDigit = false; + // deal with any possible sign up front + final int start = (chars[0] == '-' || chars[0] == '+') ? 1 : 0; + if (sz > start + 1 && chars[start] == '0' && !StrUtil.contains(str, CharUtil.DOT)) { // leading 0, skip if is a decimal number + if (chars[start + 1] == 'x' || chars[start + 1] == 'X') { // leading 0x/0X + int i = start + 2; + if (i == sz) { + return false; // str == "0x" + } + // checking hex (it can't be anything else) + for (; i < chars.length; i++) { + if ((chars[i] < '0' || chars[i] > '9') && (chars[i] < 'a' || chars[i] > 'f') && (chars[i] < 'A' || chars[i] > 'F')) { + return false; + } + } + return true; + } + if (Character.isDigit(chars[start + 1])) { + // leading 0, but not hex, must be octal + int i = start + 1; + for (; i < chars.length; i++) { + if (chars[i] < '0' || chars[i] > '7') { + return false; + } + } + return true; + } + } + sz--; // don't want to loop to the last char, check it afterwords + // for type qualifiers + int i = start; + // loop to the next to last char or to the last char if we need another digit to + // make a valid number (e.g. chars[0..5] = "1234E") + while (i < sz || (i < sz + 1 && allowSigns && !foundDigit)) { + if (chars[i] >= '0' && chars[i] <= '9') { + foundDigit = true; + allowSigns = false; + + } else if (chars[i] == '.') { + if (hasDecPoint || hasExp) { + // two decimal points or dec in exponent + return false; + } + hasDecPoint = true; + } else if (chars[i] == 'e' || chars[i] == 'E') { + // we've already taken care of hex. + if (hasExp) { + // two E's + return false; + } + if (!foundDigit) { + return false; + } + hasExp = true; + allowSigns = true; + } else if (chars[i] == '+' || chars[i] == '-') { + if (!allowSigns) { + return false; + } + allowSigns = false; + foundDigit = false; // we need a digit after the E + } else { + return false; + } + i++; + } + if (i < chars.length) { + if (chars[i] >= '0' && chars[i] <= '9') { + // no type qualifier, OK + return true; + } + if (chars[i] == 'e' || chars[i] == 'E') { + // can't have an E at the last byte + return false; + } + if (chars[i] == '.') { + if (hasDecPoint || hasExp) { + // two decimal points or dec in exponent + return false; + } + // single trailing decimal point after non-exponent is ok + return foundDigit; + } + if (!allowSigns && (chars[i] == 'd' || chars[i] == 'D' || chars[i] == 'f' || chars[i] == 'F')) { + return foundDigit; + } + if (chars[i] == 'l' || chars[i] == 'L') { + // not allowing L with an exponent or decimal point + return foundDigit && !hasExp && !hasDecPoint; + } + // last character is illegal + return false; + } + // allowSigns is true iff the val ends in 'E' + // found digit it to make sure weird stuff like '.' and '1E-' doesn't pass + return !allowSigns && foundDigit; + } + + /** + * 判断字符串是否是整数 + * + *

支持格式: + *

    + *
  1. 10进制, 不能包含前导零
  2. + *
  3. 8进制(以0开头)
  4. + *
  5. 16进制(以0x或者0X开头)
  6. + *
+ * + * @param s 校验的字符串, 只能含有 正负号、数字字符 和 {@literal X/x} + * @return 是否为 {@link Integer}类型 + * @apiNote 6.0.0 支持8进制和16进制 + * @see Integer#decode(String) + */ + public static boolean isInteger(final String s) { + if (!isNumber(s)) { + return false; + } + try { + //noinspection ResultOfMethodCallIgnored + Integer.decode(s); + } catch (final NumberFormatException e) { + return false; + } + return true; + } + + /** + * 判断字符串是否是Long类型
+ * + *

支持格式: + *

    + *
  1. 10进制, 不能包含前导零
  2. + *
  3. 8进制(以0开头)
  4. + *
  5. 16进制(以0x或者0X开头)
  6. + *
+ * + * @param s 校验的字符串, 只能含有 正负号、数字字符、{@literal X/x} 和 后缀{@literal L/l} + * @return 是否为 {@link Long}类型 + * @apiNote 6.0.0 支持8进制和16进制数字 + * @since 4.0.0 + */ + public static boolean isLong(final String s) { + if (!isNumber(s)) { + return false; + } + final char lastChar = s.charAt(s.length() - 1); + if (lastChar == 'l' || lastChar == 'L') { + return true; + } + try { + //noinspection ResultOfMethodCallIgnored + Long.decode(s); + } catch (final NumberFormatException e) { + return false; + } + return true; + } + + /** + * 判断字符串是否是浮点数 + * + * @param s String + * @return 是否为 {@link Double}类型 + */ + public static boolean isDouble(final String s) { + if (StrUtil.isBlank(s)) { + return false; + } + try { + Double.parseDouble(s); + } catch (final NumberFormatException ignore) { + return false; + } + return s.contains("."); + } + + /** + * 是否是质数(素数)
+ * 质数表的质数又称素数。指整数在一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数。 + * + * @param n 数字 + * @return 是否是质数 + */ + public static boolean isPrime(final int n) { + Assert.isTrue(n > 1, "The number must be > 1"); + if (n <= 3) { + return true; + } else if ((n & 1) == 0) { + // 快速排除偶数 + return false; + } + final int end = (int) Math.sqrt(n); + for (int i = 3; i <= end; i += 2) { + if (n % i == 0) { + return false; + } + } + return true; + } + +} diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/text/CharSequenceUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/text/CharSequenceUtil.java index f9fd0d2e5..88238fefd 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/text/CharSequenceUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/text/CharSequenceUtil.java @@ -74,7 +74,7 @@ import java.util.function.Supplier; * @author looly * @since 5.5.3 */ -public class CharSequenceUtil extends StrChecker { +public class CharSequenceUtil extends StrValidator { /** * 未找到的的位置表示,用-1表示 diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/text/StrChecker.java b/hutool-core/src/main/java/org/dromara/hutool/core/text/StrValidator.java similarity index 99% rename from hutool-core/src/main/java/org/dromara/hutool/core/text/StrChecker.java rename to hutool-core/src/main/java/org/dromara/hutool/core/text/StrValidator.java index f7a9d67d5..242237c24 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/text/StrChecker.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/text/StrValidator.java @@ -25,7 +25,7 @@ import java.util.function.Predicate; *
  • blank定义:{@code null} or 空字符串:{@code ""} or 空格、全角空格、制表符、换行符,等不可见字符
  • * */ -public class StrChecker { +public class StrValidator { /** * 字符串常量:{@code "null"}
    diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/text/placeholder/PlaceholderParser.java b/hutool-core/src/main/java/org/dromara/hutool/core/text/placeholder/PlaceholderParser.java index f202b642e..1da742e65 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/text/placeholder/PlaceholderParser.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/text/placeholder/PlaceholderParser.java @@ -14,7 +14,7 @@ package org.dromara.hutool.core.text.placeholder; import org.dromara.hutool.core.exceptions.HutoolException; import org.dromara.hutool.core.lang.Assert; -import org.dromara.hutool.core.text.StrChecker; +import org.dromara.hutool.core.text.StrValidator; import org.dromara.hutool.core.util.CharUtil; import java.util.Objects; @@ -87,8 +87,8 @@ public class PlaceholderParser implements UnaryOperator { */ public PlaceholderParser( final UnaryOperator processor, final String prefix, final String suffix, final char escape) { - Assert.isFalse(StrChecker.isEmpty(prefix), "开始符号不能为空"); - Assert.isFalse(StrChecker.isEmpty(suffix), "结束符号不能为空"); + Assert.isFalse(StrValidator.isEmpty(prefix), "开始符号不能为空"); + Assert.isFalse(StrValidator.isEmpty(suffix), "结束符号不能为空"); this.processor = Objects.requireNonNull(processor); this.open = prefix; this.openLength = prefix.length(); @@ -105,8 +105,8 @@ public class PlaceholderParser implements UnaryOperator { */ @Override public String apply(final String text) { - if (StrChecker.isEmpty(text)) { - return StrChecker.EMPTY; + if (StrValidator.isEmpty(text)) { + return StrValidator.EMPTY; } // 寻找第一个开始符号 diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/lang/func/FunctionPoolTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/func/FunctionPoolTest.java similarity index 62% rename from hutool-core/src/test/java/org/dromara/hutool/core/lang/func/FunctionPoolTest.java rename to hutool-core/src/test/java/org/dromara/hutool/core/func/FunctionPoolTest.java index 091c0cc25..50e724c84 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/lang/func/FunctionPoolTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/func/FunctionPoolTest.java @@ -1,4 +1,16 @@ -package org.dromara.hutool.core.lang.func; +/* + * Copyright (c) 2023 looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package org.dromara.hutool.core.func; import org.dromara.hutool.core.collection.ListUtil; import org.dromara.hutool.core.date.DateUtil; diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/lang/func/LambdaFactoryTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/func/LambdaFactoryTest.java similarity index 96% rename from hutool-core/src/test/java/org/dromara/hutool/core/lang/func/LambdaFactoryTest.java rename to hutool-core/src/test/java/org/dromara/hutool/core/func/LambdaFactoryTest.java index 18b0f51f7..2bea04470 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/lang/func/LambdaFactoryTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/func/LambdaFactoryTest.java @@ -1,12 +1,22 @@ -package org.dromara.hutool.core.lang.func; +/* + * Copyright (c) 2023 looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package org.dromara.hutool.core.func; import lombok.Data; import lombok.Getter; import lombok.Setter; import lombok.SneakyThrows; import org.dromara.hutool.core.collection.ListUtil; -import org.dromara.hutool.core.func.LambdaFactory; -import org.dromara.hutool.core.func.SerSupplier; import org.dromara.hutool.core.reflect.ConstructorUtil; import org.dromara.hutool.core.reflect.lookup.LookupUtil; import org.junit.jupiter.api.Assertions; diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/lang/func/LambdaUtilTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/func/LambdaUtilTest.java similarity index 87% rename from hutool-core/src/test/java/org/dromara/hutool/core/lang/func/LambdaUtilTest.java rename to hutool-core/src/test/java/org/dromara/hutool/core/func/LambdaUtilTest.java index f1488d890..e4313d5d9 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/lang/func/LambdaUtilTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/func/LambdaUtilTest.java @@ -1,20 +1,30 @@ -package org.dromara.hutool.core.lang.func; +/* + * Copyright (c) 2023 looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package org.dromara.hutool.core.func; -import org.dromara.hutool.core.func.*; -import org.dromara.hutool.core.lang.tuple.Tuple; -import org.dromara.hutool.core.reflect.MethodUtil; import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.FieldNameConstants; +import org.dromara.hutool.core.lang.tuple.Tuple; +import org.dromara.hutool.core.reflect.MethodUtil; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.io.Serializable; +import java.lang.reflect.Method; import java.util.Objects; -import java.util.function.BiConsumer; -import java.util.function.BiFunction; -import java.util.function.Function; +import java.util.function.*; import java.util.stream.Stream; public class LambdaUtilTest { @@ -307,4 +317,30 @@ public class LambdaUtilTest { return func.getClass().getName(); } } + + @Test + void getInvokeMethodTest() { + Method invokeMethod = LambdaUtil.getInvokeMethod(Predicate.class); + Assertions.assertEquals("test", invokeMethod.getName()); + + invokeMethod = LambdaUtil.getInvokeMethod(Consumer.class); + Assertions.assertEquals("accept", invokeMethod.getName()); + + invokeMethod = LambdaUtil.getInvokeMethod(Runnable.class); + Assertions.assertEquals("run", invokeMethod.getName()); + + invokeMethod = LambdaUtil.getInvokeMethod(SerFunction.class); + Assertions.assertEquals("applying", invokeMethod.getName()); + + invokeMethod = LambdaUtil.getInvokeMethod(Function.class); + Assertions.assertEquals("apply", invokeMethod.getName()); + } + + @Test + void getInvokeMethodErrorTest() { + // 非函数接口返回异常 + Assertions.assertThrows(IllegalArgumentException.class, ()->{ + LambdaUtil.getInvokeMethod(LambdaUtilTest.class); + }); + } } diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/lang/func/PredicateUtilTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/func/PredicateUtilTest.java similarity index 68% rename from hutool-core/src/test/java/org/dromara/hutool/core/lang/func/PredicateUtilTest.java rename to hutool-core/src/test/java/org/dromara/hutool/core/func/PredicateUtilTest.java index 213a64117..c4652a3ad 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/lang/func/PredicateUtilTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/func/PredicateUtilTest.java @@ -1,4 +1,16 @@ -package org.dromara.hutool.core.lang.func; +/* + * Copyright (c) 2023 looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package org.dromara.hutool.core.func; import org.dromara.hutool.core.collection.set.SetUtil; import org.dromara.hutool.core.func.PredicateUtil;