TLDR
Java使用两个字符表示UTF-16。使用Arrays.sort(不稳定的排序)会使字符排序混乱。我应该将char []转换为int []还是有更好的方法?
详细信息
Java将字符表示为UTF-16。但是Character
类本身包装char
(16位)。对于UTF-16,它将是两个char
(32位)的数组。
使用内置排序将一串UTF-16字符与数据弄乱。 (Arrays.sort使用双重数据透视快速排序,而Collections.sort使用Arrays.sort进行繁重的工作。)
具体来说,您是将char []转换为int []还是有更好的排序方式?
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] utfCodes = {128513, 128531, 128557};
String emojis = new String(utfCodes, 0, 3);
System.out.println("Initial String: " + emojis);
char[] chars = emojis.toCharArray();
Arrays.sort(chars);
System.out.println("Sorted String: " + new String(chars));
}
}
输出:
Initial String:
Sorted String: ????
答案 0 :(得分:12)
我四处张望,没有找到任何干净的方法来对两个元素进行分组来对数组进行排序,而无需使用库。
幸运的是,在此示例中,您使用hwnd
中的codePoints
来创建String
本身,因此您可以对它们进行排序并创建一个新的String
结果。
String
初始字符串:
排序字符串:
我在示例中切换了字符的顺序,因为它们已经排序。
答案 1 :(得分:6)
如果您使用的是Java 8或更高版本,那么这是一种在尊重(不破坏)多字符代码点的同时对字符串中的字符进行排序的简单方法:
int[] codepoints = someString.codePoints().sort().toArray();
String sorted = new String(codepoints, 0, codepoints.length);
在Java 8之前,我认为您要么需要使用循环来迭代原始字符串中的代码点,要么需要使用第三方库方法。
幸运的是,对字符串中的代码点进行排序并不常见,以至于上述解决方案的笨拙和相对低效的问题很少引起关注。
(您上次测试表情符号字谜是什么时候?)
答案 2 :(得分:4)
我们不能将char用于Unicode because Java's Unicode char handling is broken。
在Java的早期,Unicode代码点始终为16位(固定大小为一个字符)。但是,Unicode规范已更改为允许补充字符。这意味着Unicode字符现在是可变宽度,并且可以超过一个字符。不幸的是,在不破坏大量生产代码的情况下更改Java的char实现为时已晚。
因此,处理Unicode字符的最佳方法是直接使用代码点,例如,在JDK 1.8及更高版本上使用String.codePointAt(index)
或String.codePoints()
流。
其他来源: