2

この名前には多くのスレッドがあることを知っています。ngram を生成するコードがあります。しかし、何千もの文字列を処理するときに速度を向上させるために改善できるか知りたいですか?

例 文字列="abcdefghijkl1245ty789"

public static String[] ngrams(String s) {
        int len=12;
        String[] parts = s.split("(?!^)");
        String[] result = new String[parts.length - len + 1];
        for(int i = 0; i < parts.length - len + 1; i++) {
           StringBuilder sb = new StringBuilder();
           for(int k = 0; k < len; k++) {
               sb.append(parts[i+k]);
           }
           result[i] = sb.toString();
        }
        return result;
    }

上記のコードは文字列を取得し、指定された長さの ngrma を生成します。私の場合は12です。

4

1 に答える 1

6

もちろん:

public static String[] ngrams(String str, int length) {
    char[] chars = str.toCharArray();
    final int resultCount = chars.length - length + 1;
    String[] result = new String[resultCount];
    for (int i = 0; i < resultCount; i++) {
        result[i] = new String(chars, i, length);
    }
    return result;
}

私が行った変更:

  • 正規表現を介して分割する代わりにString#toCharArray()、単一の配列コピーを行うため、はるかに高速な方法を使用しました
  • から結果の文字列を再構築する代わりに、適切なコンストラクターStringBuilderを使用しましたが、これも単一の配列コピーのみを実行しますString
  • (パフォーマンスには必要ありませんが、それでも)メソッドシグネチャを変更してlength、テストの原因のパラメーターとして使用しました。自由に元に戻してください。メソッドの名前をngrams()tongrams12()または何かに変更してください。

または、すべてを完全に削除して、ボンネットの下で同様の作業を行うString#substring()で単純なアプローチを使用します。

public static String[] ngramsSubstring(String str, int length) {
    final int resultCount = str.length() - length + 1;
    String[] result = new String[resultCount];
    for (int i = 0; i < resultCount; i++) {
        result[i] = str.substring(i, i+length);
    }
    return result;
}

ちなみに、将来正規表現を使用する必要が生じた場合は、メソッドが使用されるたびにコンパイルするのではなく、一度コンパイルして再利用してみてください。たとえば、コードは次のようになります。

private static final Pattern EVERY_CHAR = Pattern.compile("(?!^)");

そして、メソッドでは、代わりに をString#split使用します

String[] parts = EVERY_CHAR.split(str);
于 2013-07-11T13:22:36.593 に答える