web-dev-qa-db-ja.com

JavaでのUTF-16文字列の文字のソート

[〜#〜] tldr [〜#〜]

Javaは2つの文字を使用してUTF-16を表します。 Arrays.sort(不安定なソート)混乱を文字シーケンスで使用する。 char []をint []に変換する必要がありますか、それとももっと良い方法がありますか?

詳細

Javaは文字をUTF-16として表します。ただし、Characterクラス自体はchar(16ビット)をラップします。 UTF-16の場合、2つのchars(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: ????????
16
dingy

私は少し周りを探しましたが、ライブラリを使用せずに2つの要素のグループ化によって配列を並べ替える明確な方法を見つけることができませんでした。

幸い、codePointsStringは、この例でString自体を作成するために使用したものなので、単純にそれらを並べ替えて、結果を使用して新しいStringを作成できます。

_public static void main(String[] args) {
    int[] utfCodes = {128531, 128557, 128513};
    String emojis = new String(utfCodes, 0, 3);
    System.out.println("Initial String: " + emojis);

    int[] codePoints = emojis.codePoints().sorted().toArray();
    System.out.println("Sorted String: " + new String(codePoints, 0, 3));
}
_

初期文字列:????????????

ソートされた文字列:????????????

あなたの例ではすでにソートされているので、文字の順序を入れ替えました。

12
Jacob G.

Java 8以降を使用している場合、これは、マルチ文字コードポイントを尊重する(壊さない)一方で、文字列内の文字を並べ替える簡単な方法です。

int[] codepoints = someString.codePoints().sort().toArray();
String sorted = new String(codepoints, 0, codepoints.length);

Java 8の前は、ループを使用して元の文字列のコードポイントを反復するか、サードパーティのライブラリメソッドを使用する必要があると思います。


さいわい、文字列内のコードポイントの並べ替えはあまり一般的ではないため、上記のソリューションの不格好さや相対的な非効率性はほとんど問題になりません。

(絵文字のアナグラムを最後にテストしたのはいつですか?)

6
Stephen C

Unicodeにはcharを使用できません JavaのUnicode char処理が壊れているため

Javaの初期の頃、Unicodeコードポイントは常に16ビットでした(正確に1文字に固定サイズ)。ただし、Unicode仕様は補足文字を許可するように変更されました。つまり、Unicode文字は可変幅になり、1文字より長くなる場合があります。残念ながら、大量の製品コードを壊さずにJavaのchar実装を変更するには遅すぎました。

したがって、Unicode文字を操作する最良の方法は、コードポイントを直接使用することです。たとえば、JDK 1.8以降ではString.codePointAt(index)またはString.codePoints()ストリームを使用します。

追加のソース:

4
peekay