便利なコードパーツ集!

やまろうのプログラミングTips

Java

java.text.RuleBasedCollatorで文字の順序付けルールを作る

投稿日:

2007/05

Javaには文字列の順序付けを変える便利なクラスがあるので紹介します。

package sample;

import java.text.CollationKey;
import java.text.ParseException;
import java.text.RuleBasedCollator;
import java.util.Arrays;

public class CollatorSample {
  /**
   * RuleBasedCollatorで
   * 数字よりアルファベットが弱い、英大文字より小文字が弱いと判断するルール
   * を作成し、RuleBasedCollatorを使った文字列の比較、ソート、CollatorKeyを
   * 使ったソートの結果をStringの文字列比較、ソートの結果を出力し違いを検証
   * する。
   */
  public static void main(String[] args) throws ParseException {
    //数字よりアルファベットが弱い、英大文字より小文字が弱いと判断するルール
    String rules =
      " < a < b < c < d < e < f < g < h < i < j < k < l < m"
        + " < n < o < p < q < r < s < t < u < v < w < x < y < z"
        + "  < A < B < C < D < E < F < G < H < I < J < K < L < M"
        + " < N < O < P < Q < R < S < T < U < V < W < X < Y < Z"
        + " < 0 < 1 < 2 < 3 < 4 < 5 < 6 < 7 < 8 < 9";
    RuleBasedCollator collator = new RuleBasedCollator(rules);
    String s1 = "a";
    String s2 = "1";
    //作成したルールで比較
    System.out.println(
      "collator.compare(s1, s2)=" + collator.compare(s1, s2));
    //Stringで普通に比較
    System.out.println("s1.compareTo(s2)=" + s1.compareTo(s2));

    //ソート
    String[] srcArray =
      { "888RRR", "AAA777", "BBB222", "DDD888", "666ZZZ", "aaa000" };
    String[] array1 = new String[srcArray.length];
    String[] array2 = new String[srcArray.length];
    for (int i = 0; i < srcArray.length; i++) {
      array1[i] = srcArray[i];
      array2[i] = srcArray[i];
    }
    Arrays.sort(array1);
    //Collator + Arraysでソート。1度の比較ならコスト低
    Arrays.sort(array2, collator);

    printArray(srcArray, "ソート前=            ");
    printArray(array1, "普通にソート=        ");
    printArray(array2, "Collatorでソート=    ");

    //CollatorKey + Arraysでソート
    //CollatorKeyを作るコストが発生。しかし何度も比較するならコスト低
    CollationKey[] collationKeyArray = new CollationKey[srcArray.length];
    for (int i = 0; i < srcArray.length; i++) {
      collationKeyArray[i] = collator.getCollationKey(srcArray[i]);
    }
    Arrays.sort(collationKeyArray);
    printArray(collationKeyArray, "CollationKeyでソート=");
  }

  private static void printArray(String[] array, String description) {
    System.out.print(description + "{");
    StringBuffer buf = new StringBuffer();
    for (int i = 0; i < array.length; i++) {
      buf.append(array[i]);
      buf.append(",");
    }
    System.out.println(buf.substring(0, buf.length() - 1) + "}");
  }

  private static void printArray(CollationKey[] array, String description) {
    System.out.print(description + "{");
    StringBuffer buf = new StringBuffer();
    for (int i = 0; i < array.length; i++) {
      buf.append(array[i].getSourceString());
      buf.append(",");
    }
    System.out.println(buf.substring(0, buf.length() - 1) + "}");
  }
}

[実行結果]

collator.compare(s1, s2)=-1
s1.compareTo(s2)=48
ソート前= {888RRR,AAA777,BBB222,DDD888,666ZZZ,aaa000}
普通にソート= {666ZZZ,888RRR,AAA777,BBB222,DDD888,aaa000}
Collatorでソート= {aaa000,AAA777,BBB222,DDD888,666ZZZ,888RRR}
CollationKeyでソート={aaa000,AAA777,BBB222,DDD888,666ZZZ,888RRR}

ルールどおりの比較/ソート結果ですね。
CollatorでソートとCollationKeyでソートは同じ結果になる。
ソートは何度も文字列比較をするから、件数が多いならばCollationKeyを使った方が
いいかもしれない。

スポンサーリンク

-Java

Copyright© やまろうのプログラミングTips , 2022 AllRights Reserved Powered by AFFINGER4.