1. ホーム
  2. java

[解決済み] 文字列の最初の文字を小文字にする最も効率的な方法とは?

2022-09-25 14:39:49

質問

の最初の文字を、"co" とする最も効率的な方法は何でしょうか? String の最初の文字を小文字にする最も効率的な方法は何ですか?

いろいろな方法が考えられますね。

を使う charAt()substring()

String input   = "SomeInputString";
String output  = Character.toLowerCase(input.charAt(0)) +
                   (input.length() > 1 ? input.substring(1) : "");

を使うか char 配列

 String input  = "SomeInputString";
 char c[]      = input.toCharArray();
 c[0]          = Character.toLowerCase(c[0]);
 String output = new String(c);


他にも素晴らしい方法がたくさんあると思います。お勧めの方法は何ですか?

どのように解決するのですか?

私は、有望なアプローチを JMH . 完全なベンチマーク コード .

テスト中の仮定(毎回コーナーケースをチェックするのを避けるため):入力文字列の長さは常に1より大きい。

結果

Benchmark           Mode  Cnt         Score        Error  Units
MyBenchmark.test1  thrpt   20  10463220.493 ± 288805.068  ops/s
MyBenchmark.test2  thrpt   20  14730158.709 ± 530444.444  ops/s
MyBenchmark.test3  thrpt   20  16079551.751 ±  56884.357  ops/s
MyBenchmark.test4  thrpt   20   9762578.446 ± 584316.582  ops/s
MyBenchmark.test5  thrpt   20   6093216.066 ± 180062.872  ops/s
MyBenchmark.test6  thrpt   20   2104102.578 ±  18705.805  ops/s

スコアは1秒あたりの演算量であり、多ければ多いほど良い。

テスト

  1. test1 は、まずAndyとHllinkのアプローチでした。

    string = Character.toLowerCase(string.charAt(0)) + string.substring(1);
    
    
  2. test2 は、2番目のアンディのアプローチでした。それはまた Introspector.decapitalize() は Daniel によって提案されましたが、2 つの if ステートメントがありません。まず if はテストの前提のために削除されました。2つ目は正しさに違反するため削除されました(つまり入力の "HI" を入力すると "HI" ). これはほとんど最速でした。

    char c[] = string.toCharArray();
    c[0] = Character.toLowerCase(c[0]);
    string = new String(c);
    
    
  3. test3test2 を修正したものですが、代わりに Character.toLowerCase() の代わりに32を追加していましたが、これは文字列がASCIIである場合にのみ正しく動作します。これは最速でした。 c[0] |= ' ' をマイクの コメント は同じ性能を与えました。

    char c[] = string.toCharArray();
    c[0] += 32;
    string = new String(c);
    
    
  4. test4 中古 StringBuilder .

    StringBuilder sb = new StringBuilder(string);
    sb.setCharAt(0, Character.toLowerCase(sb.charAt(0)));
    string = sb.toString();
    
    
  5. test5 2つの substring() の呼び出しがあります。

    string = string.substring(0, 1).toLowerCase() + string.substring(1);
    
    
  6. test6 を変更するためにリフレクションを使用します。 char value[] を直接Stringで変更します。これが一番遅かったです。

    try {
        Field field = String.class.getDeclaredField("value");
        field.setAccessible(true);
        char[] value = (char[]) field.get(string);
        value[0] = Character.toLowerCase(value[0]);
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    }
    
    

結論

文字列の長さが常に0より大きい場合は test2 .

そうでない場合は、コーナーケースを確認する必要があります。

public static String decapitalize(String string) {
    if (string == null || string.length() == 0) {
        return string;
    }

    char c[] = string.toCharArray();
    c[0] = Character.toLowerCase(c[0]);

    return new String(c);
}

テキストが常に ASCII であることが確実で、このコードがボトルネックになっているため、極端なパフォーマンスを求めているのであれば test3 .