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);