diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/text/StrUtil.java b/hutool-core/src/main/java/cn/hutool/v7/core/text/StrUtil.java
index a152d18f5e..dcd816e025 100644
--- a/hutool-core/src/main/java/cn/hutool/v7/core/text/StrUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/v7/core/text/StrUtil.java
@@ -288,6 +288,36 @@ public class StrUtil extends CharSequenceUtil implements StrPool {
return new String(ArrayUtil.reverse(str.toCharArray()));
}
+ /**
+ * 反转字符串
+ * 例如:abcd =》dcba
+ *
+ * 该方法按Unicode code point进行反转,支持Unicode字符的正确反转 + * 确保复杂字符不会被拆分,如表情符号等多字节字符 + *
+ * @param str 被反转的字符串 + * @return 反转后的字符串,如果输入为null则返回null + * @since 5.8.43 + */ + public static String reverseByCodePoint(String str) { + if (null == str) { + return null; + } + + //按Unicode code point方式进行反转处理 + StringBuilder result = new StringBuilder(); + for (int i = str.length(); i > 0; ) { + //获取指定位置前的code point + int codePoint = str.codePointBefore(i); + //根据code point的字符数量调整索引位置 + i -= Character.charCount(codePoint); + //将code point追加到结果中 + result.appendCodePoint(codePoint); + } + + return result.toString(); + } + // ------------------------------------------------------------------------ fill /** diff --git a/hutool-core/src/test/java/cn/hutool/v7/core/text/StrUtilTest.java b/hutool-core/src/test/java/cn/hutool/v7/core/text/StrUtilTest.java index 165551a5cc..8fc76c015f 100644 --- a/hutool-core/src/test/java/cn/hutool/v7/core/text/StrUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/v7/core/text/StrUtilTest.java @@ -27,6 +27,7 @@ import java.nio.charset.StandardCharsets; import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; /** * 字符串工具类单元测试 @@ -683,4 +684,30 @@ public class StrUtilTest { // 再次调用工具类转换,输出结果应该不变 assertEquals(originalText, StrUtil.str(buffer, StandardCharsets.UTF_8)); } + + /** + * 测试字符串反转功能,特别是对特殊字符的处理 + * 验证普通字符、中文字符以及Unicode代理对字符的反转行为 + */ + @Test + public void reverseByCodePointSpecialCharactersTest() { + //普通情况-英文字符 + assertEquals("dcba", StrUtil.reverseByCodePoint("abcd")); + + //普通情况-中文字符 + assertEquals("界世好你", StrUtil.reverseByCodePoint("你好世界")); + + //保证Unicode字符语义正确,类似emoji、组合字符 + //A😊B + String emojiStr = "A\uD83D\uDE0AB"; + String reversedEmoji = StrUtil.reverseByCodePoint(emojiStr); + //B😊A + assertEquals("B\uD83D\uDE0AA", reversedEmoji); + + //A🇨🇳B + String surrogate = "A\uD83C\uDDE8\uD83C\uDDF3B"; + String reversedSurrogate = StrUtil.reverseByCodePoint(surrogate); + //B🇨🇳A + assertNotEquals("B\uD83C\uDDE8\uD83C\uDDF3A", reversedSurrogate); + } }