mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
fix code
This commit is contained in:
parent
2d9febc7fb
commit
6a04ef4a3a
@ -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(
|
||||
|
@ -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 <R, T extends Serializable> Class<R> getRealClass(final T func) {
|
||||
final LambdaInfo lambdaInfo = resolve(func);
|
||||
return (Class<R>) 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 <T, P> BiConsumer<T, P> 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表达式,没加缓存
|
||||
|
@ -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<br>
|
||||
* 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} 对象<br>
|
||||
* 此方法不支持科学计数法
|
||||
|
@ -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
|
||||
|
||||
/**
|
||||
* 是否为数字,支持包括:
|
||||
*
|
||||
* <pre>
|
||||
* 1、10进制
|
||||
* 2、16进制数字(0x开头)
|
||||
* 3、科学计数法形式(1234E3)
|
||||
* 4、类型标识形式(123D)
|
||||
* 5、正负数标识形式(+123、-234)
|
||||
* 6、八进制数字(0开头)
|
||||
* </pre>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断字符串是否是整数
|
||||
*
|
||||
* <p>支持格式:
|
||||
* <ol>
|
||||
* <li>10进制, 不能包含前导零</li>
|
||||
* <li>8进制(以0开头)</li>
|
||||
* <li>16进制(以0x或者0X开头)</li>
|
||||
* </ol>
|
||||
*
|
||||
* @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类型<br>
|
||||
*
|
||||
* <p>支持格式:
|
||||
* <ol>
|
||||
* <li>10进制, 不能包含前导零</li>
|
||||
* <li>8进制(以0开头)</li>
|
||||
* <li>16进制(以0x或者0X开头)</li>
|
||||
* </ol>
|
||||
*
|
||||
* @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(".");
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是质数(素数)<br>
|
||||
* 质数表的质数又称素数。指整数在一个大于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<br>
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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 {
|
||||
|
||||
/**
|
||||
* 是否为数字,支持包括:
|
||||
*
|
||||
* <pre>
|
||||
* 1、10进制
|
||||
* 2、16进制数字(0x开头)
|
||||
* 3、科学计数法形式(1234E3)
|
||||
* 4、类型标识形式(123D)
|
||||
* 5、正负数标识形式(+123、-234)
|
||||
* 6、八进制数字(0开头)
|
||||
* </pre>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断字符串是否是整数
|
||||
*
|
||||
* <p>支持格式:
|
||||
* <ol>
|
||||
* <li>10进制, 不能包含前导零</li>
|
||||
* <li>8进制(以0开头)</li>
|
||||
* <li>16进制(以0x或者0X开头)</li>
|
||||
* </ol>
|
||||
*
|
||||
* @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类型<br>
|
||||
*
|
||||
* <p>支持格式:
|
||||
* <ol>
|
||||
* <li>10进制, 不能包含前导零</li>
|
||||
* <li>8进制(以0开头)</li>
|
||||
* <li>16进制(以0x或者0X开头)</li>
|
||||
* </ol>
|
||||
*
|
||||
* @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(".");
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是质数(素数)<br>
|
||||
* 质数表的质数又称素数。指整数在一个大于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;
|
||||
}
|
||||
|
||||
}
|
@ -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表示
|
||||
|
@ -25,7 +25,7 @@ import java.util.function.Predicate;
|
||||
* <li>blank定义:{@code null} or 空字符串:{@code ""} or 空格、全角空格、制表符、换行符,等不可见字符</li>
|
||||
* </ul>
|
||||
*/
|
||||
public class StrChecker {
|
||||
public class StrValidator {
|
||||
|
||||
/**
|
||||
* 字符串常量:{@code "null"} <br>
|
@ -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<String> {
|
||||
*/
|
||||
public PlaceholderParser(
|
||||
final UnaryOperator<String> 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<String> {
|
||||
*/
|
||||
@Override
|
||||
public String apply(final String text) {
|
||||
if (StrChecker.isEmpty(text)) {
|
||||
return StrChecker.EMPTY;
|
||||
if (StrValidator.isEmpty(text)) {
|
||||
return StrValidator.EMPTY;
|
||||
}
|
||||
|
||||
// 寻找第一个开始符号
|
||||
|
@ -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;
|
@ -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;
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
@ -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;
|
Loading…
x
Reference in New Issue
Block a user