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 10549f357..107476613 100755
--- a/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java
@@ -4586,4 +4586,58 @@ public class CharSequenceUtil {
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());
+ }
+
}
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 d5b0945b4..ad8e853eb 100755
--- a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java
@@ -3,6 +3,7 @@ package cn.hutool.core.util;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.math.Calculator;
+import cn.hutool.core.text.CharSequenceUtil;
import java.math.BigDecimal;
import java.math.BigInteger;
@@ -2573,6 +2574,146 @@ public class NumberUtil {
}
}
+ /**
+ * 解析转换数字字符串为 {@link java.lang.Integer } 规则如下:
+ *
+ *
+ * 1、0x开头的视为16进制数字
+ * 2、0开头的忽略开头的0
+ * 3、其它情况按照10进制转换
+ * 4、空串返回0
+ * 5、.123形式返回0(按照小于0的小数对待)
+ * 6、123.56截取小数点之前的数字,忽略小数部分
+ * 7、解析失败返回默认值
+ *
+ *
+ * @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 } 规则如下:
+ *
+ *
+ * 1、0x开头的视为16进制数字
+ * 2、0开头的忽略开头的0
+ * 3、其它情况按照10进制转换
+ * 4、空串返回0
+ * 5、.123形式返回0(按照小于0的小数对待)
+ * 6、123.56截取小数点之前的数字,忽略小数部分
+ * 7、解析失败返回默认值
+ *
+ *
+ * @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 } 规则如下:
+ *
+ *
+ * 1、0开头的忽略开头的0
+ * 2、空串返回0
+ * 3、其它情况按照10进制转换
+ * 4、.123形式返回0.123(按照小于0的小数对待)
+ *
+ *
+ * @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 } 规则如下:
+ *
+ *
+ * 1、0开头的忽略开头的0
+ * 2、空串返回0
+ * 3、其它情况按照10进制转换
+ * 4、.123形式返回0.123(按照小于0的小数对待)
+ *
+ *
+ * @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数组,使用大端字节序(高位字节在前,低位字节在后)
* 见:http://www.ruanyifeng.com/blog/2016/11/byte-order.html
diff --git a/hutool-core/src/test/java/cn/hutool/core/text/CharSequenceUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/text/CharSequenceUtilTest.java
index 2672c628b..1962f2ab6 100755
--- a/hutool-core/src/test/java/cn/hutool/core/text/CharSequenceUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/text/CharSequenceUtilTest.java
@@ -160,4 +160,53 @@ public class CharSequenceUtilTest {
a = null;
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中文"));
+
+ }
+
}
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 3a1f08330..80bfa5ee9 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
@@ -10,6 +10,12 @@ import java.math.BigInteger;
import java.math.RoundingMode;
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} 单元测试类
*
@@ -296,6 +302,23 @@ public class NumberUtilTest {
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)
public void parseNumberTest4(){
// issue#I5M55F
@@ -324,6 +347,29 @@ public class NumberUtilTest {
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
public void parseHexNumberTest() {
// 千位分隔符去掉
@@ -362,6 +408,69 @@ public class NumberUtilTest {
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
public void factorialTest(){
long factorial = NumberUtil.factorial(0);