如何在Java中真正反转String,包括BMP之外的代码点?

fge*_*fge 2 java unicode

Java的主要目标之一是使用基本原始类型表示任何语言中的每个字形; 当Java诞生时,有Unicode,此时Unicode按数字定义了字形,所有这些字形都小于或等于65535.

因此char诞生于Java:一个无符号的16位整数.

但是,Unicode领域的情况发生了变化.现在存在许多字形,其数量大于65535.

虽然Java已经承认了这一点,并且使用代理对代表了这样的代码点(本质上,char现在是一个UTF-16代码单元),但标准JDK并没有提供一种方法来反转字符串代码(StringBuilder#reverse例如,只关心个人的角色).

假设Java 8,您如何编写一个真正的字符串反转方法,即将BMP之外的代码点考虑在内?

fge*_*fge 5

一种这样的方法如下:

public static String trueReverse(final String input)
{
    final Deque<Integer> queue = new ArrayDeque<>();
    input.codePoints().forEach(queue::addFirst);

    final StringBuilder sb = new StringBuilder();
    queue.forEach(sb::appendCodePoint);

    return sb.toString();
}
Run Code Online (Sandbox Code Playgroud)

没有优化,但功能齐全.试试这个,例如:

public final class Test
{
    public static String trueReverse(final String input)
    {
        final Deque<Integer> queue = new ArrayDeque<>();
        input.codePoints().forEach(queue::addFirst);

        final StringBuilder sb = new StringBuilder();
        queue.forEach(sb::appendCodePoint);

        return sb.toString();
    }

    public static void main(final String... args)
    {
        final String input = "abc\ud83d\udca9de";

        System.out.println(trueReverse(input));
    }
}
Run Code Online (Sandbox Code Playgroud)

是的,这恰好使用了已定义的字符 ......现在,您的字体可能会或可能不会正确显示该字符.

请注意这个Unicode字符是如何在Java字符串文字中编码的:\ud83d\udca9.