From a1df46f4bda51f5db6cd083e168b63864bb814df Mon Sep 17 00:00:00 2001 From: Looly Date: Sun, 20 Mar 2022 01:38:27 +0800 Subject: [PATCH] add test --- CHANGELOG.md | 1 + .../cn/hutool/core/text/CharSequenceUtil.java | 75 ++++++++++++++----- .../core/text/CharSequenceUtilTest.java | 66 +++++++++++++--- 3 files changed, 112 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 14a41417d..cb6ac30ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ * 【poi 】 优化ExcelReader,采用只读模式(pr#2204@Gitee) * 【poi 】 优化ExcelBase,将alias放入 * 【poi 】 优化ExcelBase,将alias放入 +* 【core 】 改进StrUtil#startWith、endWith性能 ### 🐞Bug修复 * 【core 】 修复ObjectUtil.hasNull传入null返回true的问题(pr#555@Gitee) 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 4a308c14d..fc990bc62 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java @@ -694,7 +694,12 @@ public class CharSequenceUtil { /** * 是否以指定字符串开头
- * 如果给定的字符串和开头字符串都为null则返回true,否则任意一个值为null返回false + * 如果给定的字符串和开头字符串都为null则返回true,否则任意一个值为null返回false
+ *
+	 *     CharSequenceUtil.startWith("123", "123", false, true);   -- false
+	 *     CharSequenceUtil.startWith("ABCDEF", "abc", true, true); -- true
+	 *     CharSequenceUtil.startWith("abc", "abc", true, true);    -- false
+	 * 
* * @param str 被监测字符串 * @param prefix 开头字符串 @@ -711,12 +716,8 @@ public class CharSequenceUtil { return null == str && null == prefix; } - boolean isStartWith; - if (ignoreCase) { - isStartWith = str.toString().toLowerCase().startsWith(prefix.toString().toLowerCase()); - } else { - isStartWith = str.toString().startsWith(prefix.toString()); - } + boolean isStartWith = str.toString() + .regionMatches(ignoreCase, 0, prefix.toString(), 0, prefix.length()); if (isStartWith) { return (false == ignoreEquals) || (false == equals(str, prefix, ignoreCase)); @@ -799,21 +800,42 @@ public class CharSequenceUtil { * 是否以指定字符串结尾
* 如果给定的字符串和开头字符串都为null则返回true,否则任意一个值为null返回false * - * @param str 被监测字符串 - * @param suffix 结尾字符串 - * @param isIgnoreCase 是否忽略大小写 + * @param str 被监测字符串 + * @param suffix 结尾字符串 + * @param ignoreCase 是否忽略大小写 * @return 是否以指定字符串结尾 */ - public static boolean endWith(CharSequence str, CharSequence suffix, boolean isIgnoreCase) { + public static boolean endWith(CharSequence str, CharSequence suffix, boolean ignoreCase) { + return endWith(str, suffix, ignoreCase, false); + } + + /** + * 是否以指定字符串结尾
+ * 如果给定的字符串和开头字符串都为null则返回true,否则任意一个值为null返回false + * + * @param str 被监测字符串 + * @param suffix 结尾字符串 + * @param ignoreCase 是否忽略大小写 + * @param ignoreEquals 是否忽略字符串相等的情况 + * @return 是否以指定字符串结尾 + * @since 5.8.0 + */ + public static boolean endWith(CharSequence str, CharSequence suffix, boolean ignoreCase, boolean ignoreEquals) { if (null == str || null == suffix) { + if (ignoreEquals) { + return false; + } return null == str && null == suffix; } - if (isIgnoreCase) { - return str.toString().toLowerCase().endsWith(suffix.toString().toLowerCase()); - } else { - return str.toString().endsWith(suffix.toString()); + final int strOffset = str.length() - suffix.length(); + boolean isEndWith = str.toString() + .regionMatches(ignoreCase, strOffset, suffix.toString(), 0, suffix.length()); + + if (isEndWith) { + return (false == ignoreEquals) || (false == equals(str, suffix, ignoreCase)); } + return false; } /** @@ -1020,7 +1042,7 @@ public class CharSequenceUtil { // 如果被监测字符串和 return null == testStr; } - return str.toString().toLowerCase().contains(testStr.toString().toLowerCase()); + return indexOfIgnoreCase(str, testStr) > -1; } /** @@ -1420,7 +1442,7 @@ public class CharSequenceUtil { } final String str2 = str.toString(); - if (str2.toLowerCase().startsWith(prefix.toString().toLowerCase())) { + if (startWithIgnoreCase(str, prefix)) { return subSuf(str2, prefix.length());// 截取后半段 } return str2; @@ -1469,7 +1491,7 @@ public class CharSequenceUtil { } final String str2 = str.toString(); - if (str2.toLowerCase().endsWith(suffix.toString().toLowerCase())) { + if (endWithIgnoreCase(str, suffix)) { return subPre(str2, str2.length() - suffix.length()); } return str2; @@ -2641,6 +2663,21 @@ public class CharSequenceUtil { return str.length() > position && c == str.charAt(position); } + /** + * 截取第一个字串的部分字符,与第二个字符串比较(长度一致),判断截取的子串是否相同
+ * 任意一个字符串为null返回false + * + * @param str1 第一个字符串 + * @param start1 第一个字符串开始的位置 + * @param str2 第二个字符串 + * @param ignoreCase 是否忽略大小写 + * @return 子串是否相同 + * @since 3.2.1 + */ + public static boolean isSubEquals(CharSequence str1, int start1, CharSequence str2, boolean ignoreCase) { + return isSubEquals(str1, start1, str2, 0, str2.length(), ignoreCase); + } + /** * 截取两个字符串的不同部分(长度一致),判断截取的子串是否相同
* 任意一个字符串为null返回false @@ -3608,7 +3645,7 @@ public class CharSequenceUtil { * @param str 字符串 * @param startInclude 开始位置(包含) * @param endExclude 结束位置(不包含) - * @param replacedStr 被替换的字符串 + * @param replacedStr 被替换的字符串 * @return 替换后的字符串 * @since 3.2.1 */ 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 07afd2b4a..60e8d8099 100644 --- a/hutool-core/src/test/java/cn/hutool/core/text/CharSequenceUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/text/CharSequenceUtilTest.java @@ -15,7 +15,7 @@ public class CharSequenceUtilTest { } @Test - public void replaceTest2(){ + public void replaceTest2() { // https://gitee.com/dromara/hutool/issues/I4M16G String replace = "#{A}"; String result = CharSequenceUtil.replace(replace, "#{AAAAAAA}", "1"); @@ -23,14 +23,14 @@ public class CharSequenceUtilTest { } @Test - public void replaceByStrTest(){ + public void replaceByStrTest() { String replace = "SSM15930297701BeryAllen"; String result = CharSequenceUtil.replace(replace, 5, 12, "***"); Assert.assertEquals("SSM15***01BeryAllen", result); } @Test - public void addPrefixIfNotTest(){ + public void addPrefixIfNotTest() { String str = "hutool"; String result = CharSequenceUtil.addPrefixIfNot(str, "hu"); Assert.assertEquals(str, result); @@ -40,21 +40,21 @@ public class CharSequenceUtilTest { } @Test - public void addSuffixIfNotTest(){ + public void addSuffixIfNotTest() { String str = "hutool"; String result = CharSequenceUtil.addSuffixIfNot(str, "tool"); Assert.assertEquals(str, result); result = CharSequenceUtil.addSuffixIfNot(str, " is Good"); - Assert.assertEquals( str + " is Good", result); + Assert.assertEquals(str + " is Good", result); // https://gitee.com/dromara/hutool/issues/I4NS0F result = CharSequenceUtil.addSuffixIfNot("", "/"); - Assert.assertEquals( "/", result); + Assert.assertEquals("/", result); } @Test - public void normalizeTest(){ + public void normalizeTest() { // https://blog.csdn.net/oscar999/article/details/105326270 String str1 = "\u00C1"; @@ -68,7 +68,7 @@ public class CharSequenceUtilTest { } @Test - public void indexOfTest(){ + public void indexOfTest() { int index = CharSequenceUtil.indexOf("abc123", '1'); Assert.assertEquals(3, index); index = CharSequenceUtil.indexOf("abc123", '3'); @@ -78,7 +78,7 @@ public class CharSequenceUtilTest { } @Test - public void indexOfTest2(){ + public void indexOfTest2() { int index = CharSequenceUtil.indexOf("abc123", '1', 0, 3); Assert.assertEquals(-1, index); @@ -87,7 +87,7 @@ public class CharSequenceUtilTest { } @Test - public void subPreGbkTest(){ + public void subPreGbkTest() { // https://gitee.com/dromara/hutool/issues/I4JO2E String s = "华硕K42Intel酷睿i31代2G以下独立显卡不含机械硬盘固态硬盘120GB-192GB4GB-6GB"; @@ -99,9 +99,53 @@ public class CharSequenceUtilTest { } @Test - public void startWithTest(){ + public void startWithTest() { // https://gitee.com/dromara/hutool/issues/I4MV7Q Assert.assertFalse(CharSequenceUtil.startWith("123", "123", false, true)); Assert.assertFalse(CharSequenceUtil.startWith(null, null, false, true)); + Assert.assertFalse(CharSequenceUtil.startWith("abc", "abc", true, true)); + + Assert.assertTrue(CharSequenceUtil.startWithIgnoreCase(null, null)); + Assert.assertFalse(CharSequenceUtil.startWithIgnoreCase(null, "abc")); + Assert.assertFalse(CharSequenceUtil.startWithIgnoreCase("abcdef", null)); + Assert.assertTrue(CharSequenceUtil.startWithIgnoreCase("abcdef", "abc")); + Assert.assertTrue(CharSequenceUtil.startWithIgnoreCase("ABCDEF", "abc")); + } + + @Test + public void endWithTest() { + Assert.assertFalse(CharSequenceUtil.endWith("123", "123", false, true)); + Assert.assertFalse(CharSequenceUtil.endWith(null, null, false, true)); + Assert.assertFalse(CharSequenceUtil.endWith("abc", "abc", true, true)); + + Assert.assertTrue(CharSequenceUtil.endWithIgnoreCase(null, null)); + Assert.assertFalse(CharSequenceUtil.endWithIgnoreCase(null, "abc")); + Assert.assertFalse(CharSequenceUtil.endWithIgnoreCase("abcdef", null)); + Assert.assertTrue(CharSequenceUtil.endWithIgnoreCase("abcdef", "def")); + Assert.assertTrue(CharSequenceUtil.endWithIgnoreCase("ABCDEF", "def")); + } + + @Test + public void removePrefixIgnoreCaseTest(){ + Assert.assertEquals("de", CharSequenceUtil.removePrefixIgnoreCase("ABCde", "abc")); + Assert.assertEquals("de", CharSequenceUtil.removePrefixIgnoreCase("ABCde", "ABC")); + Assert.assertEquals("de", CharSequenceUtil.removePrefixIgnoreCase("ABCde", "Abc")); + Assert.assertEquals("ABCde", CharSequenceUtil.removePrefixIgnoreCase("ABCde", "")); + Assert.assertEquals("ABCde", CharSequenceUtil.removePrefixIgnoreCase("ABCde", null)); + Assert.assertEquals("", CharSequenceUtil.removePrefixIgnoreCase("ABCde", "ABCde")); + Assert.assertEquals("ABCde", CharSequenceUtil.removePrefixIgnoreCase("ABCde", "ABCdef")); + Assert.assertNull(CharSequenceUtil.removePrefixIgnoreCase(null, "ABCdef")); + } + + @Test + public void removeSuffixIgnoreCaseTest(){ + Assert.assertEquals("AB", CharSequenceUtil.removeSuffixIgnoreCase("ABCde", "cde")); + Assert.assertEquals("AB", CharSequenceUtil.removeSuffixIgnoreCase("ABCde", "CDE")); + Assert.assertEquals("AB", CharSequenceUtil.removeSuffixIgnoreCase("ABCde", "Cde")); + Assert.assertEquals("ABCde", CharSequenceUtil.removeSuffixIgnoreCase("ABCde", "")); + Assert.assertEquals("ABCde", CharSequenceUtil.removeSuffixIgnoreCase("ABCde", null)); + Assert.assertEquals("", CharSequenceUtil.removeSuffixIgnoreCase("ABCde", "ABCde")); + Assert.assertEquals("ABCde", CharSequenceUtil.removeSuffixIgnoreCase("ABCde", "ABCdef")); + Assert.assertNull(CharSequenceUtil.removeSuffixIgnoreCase(null, "ABCdef")); } }