diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e102cda1..5bca495dc 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * 【core 】 Converter转换规则变更,空对象、空值转为Bean时,创建默认对象,而非null(issue#3649@Github) * 【core 】 UrlQuery增加remove方法 * 【extra 】 增加JakartaMailUtil,支持新包名的mail +* 【core 】 CharSequenceUtil增加removeAllPrefix和removeAllSuffix方法(pr#3655@Github) ### 🐞Bug修复 * 【core 】 修复因RFC3986理解有误导致的UrlPath处理冒号转义问题(issue#IAAE88@Gitee) diff --git a/bin/sync.sh b/bin/sync.sh index a00a16b52..804660f3b 100644 --- a/bin/sync.sh +++ b/bin/sync.sh @@ -2,3 +2,4 @@ git checkout v5-dev git pull osc v5-dev +git pull origin v5-dev 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 42fff4a12..3f723c311 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 @@ -1464,24 +1464,35 @@ public class CharSequenceUtil { } return str2; } - + /** - * 去掉指定所有前缀 + * 去掉指定所有前缀,如: + *
{@code + * str=abcdef, prefix=ab => return cdef + * str=ababcdef, prefix=ab => return cdef + * str=ababcdef, prefix="" => return ababcdef + * str=ababcdef, prefix=null => return ababcdef + * }* - * @param str 字符串 - * @param prefix 前缀 - * @return 切掉所有前缀的字符串,若前缀不是 preffix, 返回原字符串 + * @param str 字符串,空返回原字符串 + * @param prefix 前缀,空返回原字符串 + * @return 去掉所有前缀的字符串,若前缀不是 preffix, 返回原字符串 + * @since 5.8.30 */ public static String removeAllPrefix(CharSequence str, CharSequence prefix) { if (isEmpty(str) || isEmpty(prefix)) { return str(str); } - String str2 = str.toString(); - while (str2.startsWith(prefix.toString())) { - str2 = removePrefix(str2, prefix); + final String prefixStr = prefix.toString(); + final int prefixLength = prefixStr.length(); + + final String str2 = str.toString(); + int toIndex = 0; + while (str2.startsWith(prefixStr, toIndex)) { + toIndex += prefixLength; } - return str2; + return subSuf(str2, toIndex); } /** @@ -1521,26 +1532,37 @@ public class CharSequenceUtil { } return str2; } - + /** - * 去掉指定所有后缀 + * 去掉指定所有后缀,如: + *
{@code + * str=11abab, suffix=ab => return 11 + * str=11ab, suffix=ab => return 11 + * str=11ab, suffix="" => return 11ab + * str=11ab, suffix=null => return 11ab + * }* - * @param str 字符串 - * @param suffix 后缀 - * @return 切掉所有后缀的字符串,若后缀不是 suffix, 返回原字符串 + * @param str 字符串,空返回原字符串 + * @param suffix 后缀字符串,空返回原字符串 + * @return 去掉所有后缀的字符串,若后缀不是 suffix, 返回原字符串 + * @since 5.8.30 */ public static String removeAllSuffix(CharSequence str, CharSequence suffix) { if (isEmpty(str) || isEmpty(suffix)) { return str(str); } - String str2 = str.toString(); - while (str2.endsWith(suffix.toString())) { - str2 = removeSuffix(str2, suffix); + final String suffixStr = suffix.toString(); + final int suffixLength = suffixStr.length(); + + final String str2 = str.toString(); + int toIndex = str2.length(); + while (str2.startsWith(suffixStr, toIndex - suffixLength)){ + toIndex -= suffixLength; } - return str2; + return subPre(str2, toIndex); } - + /** * 去掉指定后缀,并小写首字母 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 3914d806c..0e0c4d2ed 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 @@ -6,12 +6,14 @@ import org.junit.Test; import java.util.regex.Pattern; +import static org.junit.Assert.*; + public class CharSequenceUtilTest { @Test public void replaceTest() { String actual = CharSequenceUtil.replace("SSM15930297701BeryAllen", Pattern.compile("[0-9]"), matcher -> ""); - Assert.assertEquals("SSMBeryAllen", actual); + assertEquals("SSMBeryAllen", actual); } @Test @@ -19,38 +21,38 @@ public class CharSequenceUtilTest { // https://gitee.com/dromara/hutool/issues/I4M16G String replace = "#{A}"; String result = CharSequenceUtil.replace(replace, "#{AAAAAAA}", "1"); - Assert.assertEquals(replace, result); + assertEquals(replace, result); } @Test public void replaceByStrTest() { String replace = "SSM15930297701BeryAllen"; String result = CharSequenceUtil.replaceByCodePoint(replace, 5, 12, "***"); - Assert.assertEquals("SSM15***01BeryAllen", result); + assertEquals("SSM15***01BeryAllen", result); } @Test public void addPrefixIfNotTest() { String str = "hutool"; String result = CharSequenceUtil.addPrefixIfNot(str, "hu"); - Assert.assertEquals(str, result); + assertEquals(str, result); result = CharSequenceUtil.addPrefixIfNot(str, "Good"); - Assert.assertEquals("Good" + str, result); + assertEquals("Good" + str, result); } @Test public void addSuffixIfNotTest() { String str = "hutool"; String result = CharSequenceUtil.addSuffixIfNot(str, "tool"); - Assert.assertEquals(str, result); + assertEquals(str, result); result = CharSequenceUtil.addSuffixIfNot(str, " is Good"); - Assert.assertEquals(str + " is Good", result); + assertEquals(str + " is Good", result); // https://gitee.com/dromara/hutool/issues/I4NS0F result = CharSequenceUtil.addSuffixIfNot("", "/"); - Assert.assertEquals("/", result); + assertEquals("/", result); } @Test @@ -64,26 +66,26 @@ public class CharSequenceUtilTest { str1 = CharSequenceUtil.normalize(str1); str2 = CharSequenceUtil.normalize(str2); - Assert.assertEquals(str1, str2); + assertEquals(str1, str2); } @Test public void indexOfTest() { int index = CharSequenceUtil.indexOf("abc123", '1'); - Assert.assertEquals(3, index); + assertEquals(3, index); index = CharSequenceUtil.indexOf("abc123", '3'); - Assert.assertEquals(5, index); + assertEquals(5, index); index = CharSequenceUtil.indexOf("abc123", 'a'); - Assert.assertEquals(0, index); + assertEquals(0, index); } @Test public void indexOfTest2() { int index = CharSequenceUtil.indexOf("abc123", '1', 0, 3); - Assert.assertEquals(-1, index); + assertEquals(-1, index); index = CharSequenceUtil.indexOf("abc123", 'b', 0, 3); - Assert.assertEquals(1, index); + assertEquals(1, index); } @Test @@ -92,73 +94,73 @@ public class CharSequenceUtilTest { String s = "华硕K42Intel酷睿i31代2G以下独立显卡不含机械硬盘固态硬盘120GB-192GB4GB-6GB"; String v = CharSequenceUtil.subPreGbk(s, 40, false); - Assert.assertEquals(39, v.getBytes(CharsetUtil.CHARSET_GBK).length); + assertEquals(39, v.getBytes(CharsetUtil.CHARSET_GBK).length); v = CharSequenceUtil.subPreGbk(s, 40, true); - Assert.assertEquals(41, v.getBytes(CharsetUtil.CHARSET_GBK).length); + assertEquals(41, v.getBytes(CharsetUtil.CHARSET_GBK).length); } @Test 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)); + assertFalse(CharSequenceUtil.startWith("123", "123", false, true)); + assertFalse(CharSequenceUtil.startWith(null, null, false, true)); + 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)); + assertFalse(CharSequenceUtil.startWithIgnoreCase(null, "abc")); + 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)); + assertFalse(CharSequenceUtil.endWith("123", "123", false, true)); + assertFalse(CharSequenceUtil.endWith(null, null, false, true)); + 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)); + assertFalse(CharSequenceUtil.endWithIgnoreCase(null, "abc")); + 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")); + assertEquals("de", CharSequenceUtil.removePrefixIgnoreCase("ABCde", "abc")); + assertEquals("de", CharSequenceUtil.removePrefixIgnoreCase("ABCde", "ABC")); + assertEquals("de", CharSequenceUtil.removePrefixIgnoreCase("ABCde", "Abc")); + assertEquals("ABCde", CharSequenceUtil.removePrefixIgnoreCase("ABCde", "")); + assertEquals("ABCde", CharSequenceUtil.removePrefixIgnoreCase("ABCde", null)); + assertEquals("", CharSequenceUtil.removePrefixIgnoreCase("ABCde", "ABCde")); + assertEquals("ABCde", CharSequenceUtil.removePrefixIgnoreCase("ABCde", "ABCdef")); + 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")); + assertEquals("AB", CharSequenceUtil.removeSuffixIgnoreCase("ABCde", "cde")); + assertEquals("AB", CharSequenceUtil.removeSuffixIgnoreCase("ABCde", "CDE")); + assertEquals("AB", CharSequenceUtil.removeSuffixIgnoreCase("ABCde", "Cde")); + assertEquals("ABCde", CharSequenceUtil.removeSuffixIgnoreCase("ABCde", "")); + assertEquals("ABCde", CharSequenceUtil.removeSuffixIgnoreCase("ABCde", null)); + assertEquals("", CharSequenceUtil.removeSuffixIgnoreCase("ABCde", "ABCde")); + assertEquals("ABCde", CharSequenceUtil.removeSuffixIgnoreCase("ABCde", "ABCdef")); + assertNull(CharSequenceUtil.removeSuffixIgnoreCase(null, "ABCdef")); } @Test public void trimToNullTest(){ String a = " "; - Assert.assertNull(CharSequenceUtil.trimToNull(a)); + assertNull(CharSequenceUtil.trimToNull(a)); a = ""; - Assert.assertNull(CharSequenceUtil.trimToNull(a)); + assertNull(CharSequenceUtil.trimToNull(a)); a = null; - Assert.assertNull(CharSequenceUtil.trimToNull(a)); + assertNull(CharSequenceUtil.trimToNull(a)); } @Test @@ -166,22 +168,22 @@ public class CharSequenceUtilTest { // -------------------------- None match ----------------------- - Assert.assertEquals("", CharSequenceUtil.commonPrefix("", "abc")); - Assert.assertEquals("", CharSequenceUtil.commonPrefix(null, "abc")); - Assert.assertEquals("", CharSequenceUtil.commonPrefix("abc", null)); - Assert.assertEquals("", CharSequenceUtil.commonPrefix("abc", "")); + assertEquals("", CharSequenceUtil.commonPrefix("", "abc")); + assertEquals("", CharSequenceUtil.commonPrefix(null, "abc")); + assertEquals("", CharSequenceUtil.commonPrefix("abc", null)); + assertEquals("", CharSequenceUtil.commonPrefix("abc", "")); - Assert.assertEquals("", CharSequenceUtil.commonPrefix("azzzj", "bzzzj")); + assertEquals("", CharSequenceUtil.commonPrefix("azzzj", "bzzzj")); - Assert.assertEquals("", CharSequenceUtil.commonPrefix("english中文", "french中文")); + assertEquals("", CharSequenceUtil.commonPrefix("english中文", "french中文")); // -------------------------- Matched ----------------------- - Assert.assertEquals("name_", CharSequenceUtil.commonPrefix("name_abc", "name_efg")); + assertEquals("name_", CharSequenceUtil.commonPrefix("name_abc", "name_efg")); - Assert.assertEquals("zzzj", CharSequenceUtil.commonPrefix("zzzja", "zzzjb")); + assertEquals("zzzj", CharSequenceUtil.commonPrefix("zzzja", "zzzjb")); - Assert.assertEquals("中文", CharSequenceUtil.commonPrefix("中文english", "中文french")); + assertEquals("中文", CharSequenceUtil.commonPrefix("中文english", "中文french")); // { space * 10 } + "abc" final String str1 = CharSequenceUtil.repeat(CharSequenceUtil.SPACE, 10) + "abc"; @@ -190,7 +192,7 @@ public class CharSequenceUtilTest { final String str2 = CharSequenceUtil.repeat(CharSequenceUtil.SPACE, 5) + "efg"; // Expect common prefix: { space * 5 } - Assert.assertEquals(CharSequenceUtil.repeat(CharSequenceUtil.SPACE, 5), CharSequenceUtil.commonPrefix(str1, str2)); + assertEquals(CharSequenceUtil.repeat(CharSequenceUtil.SPACE, 5), CharSequenceUtil.commonPrefix(str1, str2)); } @Test @@ -198,22 +200,22 @@ public class CharSequenceUtilTest { // -------------------------- None match ----------------------- - Assert.assertEquals("", CharSequenceUtil.commonSuffix("", "abc")); - Assert.assertEquals("", CharSequenceUtil.commonSuffix(null, "abc")); - Assert.assertEquals("", CharSequenceUtil.commonSuffix("abc", null)); - Assert.assertEquals("", CharSequenceUtil.commonSuffix("abc", "")); + assertEquals("", CharSequenceUtil.commonSuffix("", "abc")); + assertEquals("", CharSequenceUtil.commonSuffix(null, "abc")); + assertEquals("", CharSequenceUtil.commonSuffix("abc", null)); + assertEquals("", CharSequenceUtil.commonSuffix("abc", "")); - Assert.assertEquals("", CharSequenceUtil.commonSuffix("zzzja", "zzzjb")); + assertEquals("", CharSequenceUtil.commonSuffix("zzzja", "zzzjb")); - Assert.assertEquals("", CharSequenceUtil.commonSuffix("中文english", "中文Korean")); + assertEquals("", CharSequenceUtil.commonSuffix("中文english", "中文Korean")); // -------------------------- Matched ----------------------- - Assert.assertEquals("_name", CharSequenceUtil.commonSuffix("abc_name", "efg_name")); + assertEquals("_name", CharSequenceUtil.commonSuffix("abc_name", "efg_name")); - Assert.assertEquals("zzzj", CharSequenceUtil.commonSuffix("abczzzj", "efgzzzj")); + assertEquals("zzzj", CharSequenceUtil.commonSuffix("abczzzj", "efgzzzj")); - Assert.assertEquals("中文", CharSequenceUtil.commonSuffix("english中文", "Korean中文")); + assertEquals("中文", CharSequenceUtil.commonSuffix("english中文", "Korean中文")); // "abc" + { space * 10 } final String str1 = "abc" + CharSequenceUtil.repeat(CharSequenceUtil.SPACE, 10); @@ -222,7 +224,7 @@ public class CharSequenceUtilTest { final String str2 = "efg" + CharSequenceUtil.repeat(CharSequenceUtil.SPACE, 15); // Expect common suffix: { space * 10 } - Assert.assertEquals(CharSequenceUtil.repeat(CharSequenceUtil.SPACE, 10), CharSequenceUtil.commonSuffix(str1, str2)); + assertEquals(CharSequenceUtil.repeat(CharSequenceUtil.SPACE, 10), CharSequenceUtil.commonSuffix(str1, str2)); } @Test @@ -234,13 +236,62 @@ public class CharSequenceUtilTest { Assert.assertTrue(CharSequenceUtil.containsOnly("asdf", 'a', 's', 'd', 'f')); // 测试字符串包含testChars中的字符和其它字符 - Assert.assertFalse(CharSequenceUtil.containsOnly("asdf123", 'a', 's', 'd', 'f')); + assertFalse(CharSequenceUtil.containsOnly("asdf123", 'a', 's', 'd', 'f')); // 测试字符串不包含testChars中的任何字符 - Assert.assertFalse(CharSequenceUtil.containsOnly("hello", 'a', 'b')); + assertFalse(CharSequenceUtil.containsOnly("hello", 'a', 'b')); // 测试字符串为null - Assert.assertTrue(CharSequenceUtil.containsOnly(null, 'a', 'b')); + assertTrue(CharSequenceUtil.containsOnly(null, 'a', 'b')); } + @Test + public void removeAllPrefixTest() { + final String prefix = "ab"; + + String str = "ababcdef"; + String result = CharSequenceUtil.removeAllPrefix(str, prefix); + assertEquals("cdef", result); + + str = "abcdef"; + result = CharSequenceUtil.removeAllPrefix(str, prefix); + assertEquals("cdef", result); + + str = "cdef"; + result = CharSequenceUtil.removeAllPrefix(str, prefix); + assertEquals("cdef", result); + + str = ""; + result = CharSequenceUtil.removeAllPrefix(str, prefix); + assertEquals("", result); + + str = null; + result = CharSequenceUtil.removeAllPrefix(str, prefix); + assertNull(result); + } + + @Test + public void removeAllSuffixTest() { + final String prefix = "ab"; + + String str = "cdefabab"; + String result = CharSequenceUtil.removeAllSuffix(str, prefix); + assertEquals("cdef", result); + + str = "cdefab"; + result = CharSequenceUtil.removeAllSuffix(str, prefix); + assertEquals("cdef", result); + + str = "cdef"; + result = CharSequenceUtil.removeAllSuffix(str, prefix); + assertEquals("cdef", result); + + str = ""; + result = CharSequenceUtil.removeAllSuffix(str, prefix); + assertEquals("", result); + + str = null; + result = CharSequenceUtil.removeAllSuffix(str, prefix); + assertNull(result); + } }