Merge pull request #3007 from zzzj1233/v5-dev

Feat: NumberUtil重载parseXXX方法, 解析失败返回默认值, 代替抛出异常
This commit is contained in:
Golden Looly 2023-03-23 23:52:16 +08:00 committed by GitHub
commit 59470d1669
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 353 additions and 0 deletions

View File

@ -4586,4 +4586,58 @@ public class CharSequenceUtil {
return false; return false;
} }
/**
*
* @param str1 字符串1
* @param str2 字符串2
* @return 字符串1和字符串2的公共前缀
*/
public static CharSequence commonPrefix(CharSequence str1, CharSequence str2) {
if (isBlank(str1) || isBlank(str2)) {
return EMPTY;
}
int minLength = Math.min(str1.length(), str2.length());
int index = 0;
for (; index < minLength; index++) {
if (str1.charAt(index) != str2.charAt(index)) {
break;
}
}
return str1.subSequence(0, index);
}
/**
*
* @param str1 字符串1
* @param str2 字符串2
* @return 字符串1和字符串2的公共后缀
*/
public static CharSequence commonSuffix(CharSequence str1, CharSequence str2) {
if (isBlank(str1) || isBlank(str2)) {
return EMPTY;
}
int str1Index = str1.length() - 1;
int str2Index = str2.length() - 1;
for (; str1Index >= 0 && str2Index >= 0; str1Index--, str2Index--) {
if (str1.charAt(str1Index) != str2.charAt(str2Index)) {
break;
}
}
return str1.subSequence(str1Index + 1, str1.length());
}
} }

View File

@ -3,6 +3,7 @@ package cn.hutool.core.util;
import cn.hutool.core.exceptions.UtilException; import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.core.math.Calculator; import cn.hutool.core.math.Calculator;
import cn.hutool.core.text.CharSequenceUtil;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
@ -2573,6 +2574,146 @@ public class NumberUtil {
} }
} }
/**
* 解析转换数字字符串为 {@link java.lang.Integer } 规则如下
*
* <pre>
* 10x开头的视为16进制数字
* 20开头的忽略开头的0
* 3其它情况按照10进制转换
* 4空串返回0
* 5.123形式返回0按照小于0的小数对待
* 6123.56截取小数点之前的数字忽略小数部分
* 7解析失败返回默认值
* </pre>
*
* @param numberStr 数字字符串支持0x开头0开头和普通十进制
* @param defaultValue 如果解析失败, 将返回defaultValue, 允许null
* @return Integer
*/
public static Integer parseInt(String numberStr, Integer defaultValue) {
if (CharSequenceUtil.isBlank(numberStr)) {
return defaultValue;
}
try {
return parseInt(numberStr);
} catch (NumberFormatException ignore) {
}
return defaultValue;
}
/**
* 解析转换数字字符串为 {@link java.lang.Long } 规则如下
*
* <pre>
* 10x开头的视为16进制数字
* 20开头的忽略开头的0
* 3其它情况按照10进制转换
* 4空串返回0
* 5.123形式返回0按照小于0的小数对待
* 6123.56截取小数点之前的数字忽略小数部分
* 7解析失败返回默认值
* </pre>
*
* @param numberStr 数字字符串支持0x开头0开头和普通十进制
* @param defaultValue 如果解析失败, 将返回defaultValue, 允许null
* @return Long
*/
public static Long parseLong(String numberStr, Long defaultValue) {
if (CharSequenceUtil.isBlank(numberStr)) {
return defaultValue;
}
try {
return parseLong(numberStr);
} catch (NumberFormatException ignore) {
}
return defaultValue;
}
/**
* 解析转换数字字符串为 {@link java.lang.Float } 规则如下
*
* <pre>
* 10开头的忽略开头的0
* 2空串返回0
* 3其它情况按照10进制转换
* 4.123形式返回0.123按照小于0的小数对待
* </pre>
*
* @param numberStr 数字字符串支持0x开头0开头和普通十进制
* @param defaultValue 如果解析失败, 将返回defaultValue, 允许null
* @return Float
*/
public static Float parseFloat(String numberStr, Float defaultValue) {
if (CharSequenceUtil.isBlank(numberStr)) {
return defaultValue;
}
try {
return parseFloat(numberStr);
} catch (NumberFormatException ignore) {
}
return defaultValue;
}
/**
* 解析转换数字字符串为 {@link java.lang.Double } 规则如下
*
* <pre>
* 10开头的忽略开头的0
* 2空串返回0
* 3其它情况按照10进制转换
* 4.123形式返回0.123按照小于0的小数对待
* </pre>
*
* @param numberStr 数字字符串支持0x开头0开头和普通十进制
* @param defaultValue 如果解析失败, 将返回defaultValue, 允许null
* @return Double
*/
public static Double parseDouble(String numberStr, Double defaultValue) {
if (CharSequenceUtil.isBlank(numberStr)) {
return defaultValue;
}
try {
return parseDouble(numberStr);
} catch (NumberFormatException ignore) {
}
return defaultValue;
}
/**
* 将指定字符串转换为{@link Number }
* 此方法不支持科学计数法
*
* @param numberStr Number字符串
* @param defaultValue 如果解析失败, 将返回defaultValue, 允许null
* @return Number对象
*/
public static Number parseNumber(String numberStr, Number defaultValue) {
if (CharSequenceUtil.isBlank(numberStr)) {
return defaultValue;
}
try {
return parseNumber(numberStr);
} catch (NumberFormatException ignore) {
}
return defaultValue;
}
/** /**
* int值转byte数组使用大端字节序高位字节在前低位字节在后<br> * int值转byte数组使用大端字节序高位字节在前低位字节在后<br>
* <a href="http://www.ruanyifeng.com/blog/2016/11/byte-order.html">http://www.ruanyifeng.com/blog/2016/11/byte-order.html</a> * <a href="http://www.ruanyifeng.com/blog/2016/11/byte-order.html">http://www.ruanyifeng.com/blog/2016/11/byte-order.html</a>

View File

@ -160,4 +160,53 @@ public class CharSequenceUtilTest {
a = null; a = null;
Assert.assertNull(CharSequenceUtil.trimToNull(a)); Assert.assertNull(CharSequenceUtil.trimToNull(a));
} }
@Test
public void commonPrefixTest() throws Exception{
// -------------------------- None match -----------------------
Assert.assertEquals("", CharSequenceUtil.commonPrefix("", "abc"));
Assert.assertEquals("", CharSequenceUtil.commonPrefix(null, "abc"));
Assert.assertEquals("", CharSequenceUtil.commonPrefix("abc", null));
Assert.assertEquals("", CharSequenceUtil.commonPrefix("abc", ""));
Assert.assertEquals("", CharSequenceUtil.commonPrefix("azzzj", "bzzzj"));
Assert.assertEquals("", CharSequenceUtil.commonPrefix("english中文", "french中文"));
// -------------------------- Matched -----------------------
Assert.assertEquals("name_", CharSequenceUtil.commonPrefix("name_abc", "name_efg"));
Assert.assertEquals("zzzj", CharSequenceUtil.commonPrefix("zzzja", "zzzjb"));
Assert.assertEquals("中文", CharSequenceUtil.commonPrefix("中文english", "中文french"));
}
@Test
public void commonSuffixTest() throws Exception{
// -------------------------- None match -----------------------
Assert.assertEquals("", CharSequenceUtil.commonSuffix("", "abc"));
Assert.assertEquals("", CharSequenceUtil.commonSuffix(null, "abc"));
Assert.assertEquals("", CharSequenceUtil.commonSuffix("abc", null));
Assert.assertEquals("", CharSequenceUtil.commonSuffix("abc", ""));
Assert.assertEquals("", CharSequenceUtil.commonSuffix("zzzja", "zzzjb"));
Assert.assertEquals("", CharSequenceUtil.commonSuffix("中文english", "中文Korean"));
// -------------------------- Matched -----------------------
Assert.assertEquals("_name", CharSequenceUtil.commonSuffix("abc_name", "efg_name"));
Assert.assertEquals("zzzj", CharSequenceUtil.commonSuffix("abczzzj", "efgzzzj"));
Assert.assertEquals("中文", CharSequenceUtil.commonSuffix("english中文", "Korean中文"));
}
} }

View File

@ -10,6 +10,12 @@ import java.math.BigInteger;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.util.Set; import java.util.Set;
import static cn.hutool.core.util.NumberUtil.parseDouble;
import static cn.hutool.core.util.NumberUtil.parseFloat;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
/** /**
* {@link NumberUtil} 单元测试类 * {@link NumberUtil} 单元测试类
* *
@ -296,6 +302,23 @@ public class NumberUtilTest {
Assert.assertEquals(0, v1); Assert.assertEquals(0, v1);
} }
@Test
public void parseIntTest4() {
// -------------------------- Parse failed -----------------------
assertThat(NumberUtil.parseInt("abc", null), nullValue());
assertThat(NumberUtil.parseInt("abc", 456), equalTo(456));
// -------------------------- Parse success -----------------------
assertThat(NumberUtil.parseInt("123.abc", 789), equalTo(123));
assertThat(NumberUtil.parseInt("123.3", null), equalTo(123));
}
@Test(expected = NumberFormatException.class) @Test(expected = NumberFormatException.class)
public void parseNumberTest4(){ public void parseNumberTest4(){
// issue#I5M55F // issue#I5M55F
@ -324,6 +347,29 @@ public class NumberUtilTest {
Assert.assertTrue(number instanceof BigDecimal); Assert.assertTrue(number instanceof BigDecimal);
} }
@Test
public void parseNumberTest3(){
// -------------------------- Parse failed -----------------------
assertThat(NumberUtil.parseNumber("abc", null), nullValue());
assertThat(NumberUtil.parseNumber(StrUtil.EMPTY, null), nullValue());
assertThat(NumberUtil.parseNumber(StrUtil.repeat(StrUtil.SPACE, 10), null), nullValue());
assertThat(NumberUtil.parseNumber("abc", 456).intValue(), equalTo(456));
// -------------------------- Parse success -----------------------
assertThat(NumberUtil.parseNumber("123.abc", 789).intValue(), equalTo(123));
assertThat(NumberUtil.parseNumber("123.3", null).doubleValue(), equalTo(123.3D));
assertThat(NumberUtil.parseNumber("0.123.3", null).doubleValue(), equalTo(0.123D));
}
@Test @Test
public void parseHexNumberTest() { public void parseHexNumberTest() {
// 千位分隔符去掉 // 千位分隔符去掉
@ -362,6 +408,69 @@ public class NumberUtilTest {
Assert.assertEquals(0, number); Assert.assertEquals(0, number);
} }
@Test
public void parseLongTest2() {
// -------------------------- Parse failed -----------------------
Long v1 = NumberUtil.parseLong(null, null);
assertThat(v1, nullValue());
Long v2 = NumberUtil.parseLong(StrUtil.EMPTY, null);
assertThat(v2, nullValue());
Long v3 = NumberUtil.parseLong("L3221", 1233L);
assertThat(v3, equalTo(1233L));
// -------------------------- Parse success -----------------------
Long v4 = NumberUtil.parseLong("1233L", null);
assertThat(v4, equalTo(1233L));
}
@Test
public void parseFloatTest() throws Exception {
// -------------------------- Parse failed -----------------------
assertThat(parseFloat("abc", null), nullValue());
assertThat(parseFloat("a123.33", null), nullValue());
assertThat(parseFloat("..123", null), nullValue());
assertThat(parseFloat(StrUtil.EMPTY, 1233F), equalTo(1233F));
// -------------------------- Parse success -----------------------
assertThat(parseFloat("123.33a", null), equalTo(123.33F));
assertThat(parseFloat(".123", null), equalTo(0.123F));
}
@Test
public void parseDoubleTest() throws Exception {
// -------------------------- Parse failed -----------------------
assertThat(parseDouble("abc", null), nullValue());
assertThat(parseDouble("a123.33", null), nullValue());
assertThat(parseDouble("..123", null), nullValue());
assertThat(parseDouble(StrUtil.EMPTY, 1233D), equalTo(1233D));
// -------------------------- Parse success -----------------------
assertThat(parseDouble("123.33a", null), equalTo(123.33D));
assertThat(parseDouble(".123", null), equalTo(0.123D));
}
@Test @Test
public void factorialTest(){ public void factorialTest(){
long factorial = NumberUtil.factorial(0); long factorial = NumberUtil.factorial(0);