对Java中的UTF-16字符串中的字符进行排序

时间:2019-04-23 02:00:28

标签: java string sorting utf-16

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: ????

3 个答案:

答案 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()流。

其他来源: