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秒あたりの操作数で、多ければ多いほど良いです。
_test1
_は最初のAndyとHllinkのアプローチでした:
_string = Character.toLowerCase(string.charAt(0)) + string.substring(1);
_
_test2
_は2番目のAndyのアプローチでした。また、ダニエルによって提案された Introspector.decapitalize()
ですが、2つのif
ステートメントはありません。最初のif
は、テストの前提のため削除されました。 2番目のものは、正確性に違反していたため削除されました(つまり、入力_"HI"
_は_"HI"
_を返します)。これはほぼ最速でした。
_char c[] = string.toCharArray();
c[0] = Character.toLowerCase(c[0]);
string = new String(c);
_
_test3
_は_test2
_の修正ですが、Character.toLowerCase()
の代わりに32を追加しました。これは、文字列がASCIIである場合にのみ正しく動作します。これが最速でした。マイクの コメント の_c[0] |= ' '
_は同じパフォーマンスを示しました。
_char c[] = string.toCharArray();
c[0] += 32;
string = new String(c);
_
_test4
_使用済みStringBuilder
。
_StringBuilder sb = new StringBuilder(string);
sb.setCharAt(0, Character.toLowerCase(sb.charAt(0)));
string = sb.toString();
_
_test5
_は2つのsubstring()
呼び出しを使用しました。
_string = string.substring(0, 1).toLowerCase() + string.substring(1);
_
_test6
_はリフレクションを使用して、Stringで直接 _char value[]
_ を変更します。これが最も遅かった。
_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
_を使用してください。
サードパーティのライブラリを使用したくない場合は、素敵な代替手段に出くわしました:
import Java.beans.Introspector;
Assert.assertEquals("someInputString", Introspector.decapitalize("SomeInputString"));
文字列操作に関しては、ジャカルタコモンズラング StringUtils をご覧ください。
Apache Commonsを使用する場合は、次のことができます。
import org.Apache.commons.lang3.text.WordUtils;
[...]
String s = "SomeString";
String firstLower = WordUtils.uncapitalize(s);
結果:someString
文字指向のアプローチにもかかわらず、文字列指向のソリューションを提案します。 String.toLowerCase はロケール固有であるため、この問題を考慮します。 String.toLowerCase
は、 Character.toLowerCase に従って小文字を優先することです。 Character.toLowerCase は補助文字を処理できないため、char指向のソリューションは完全なUnicode互換ではありません。
public static final String uncapitalize(final String originalStr,
final Locale locale) {
final int splitIndex = 1;
final String result;
if (originalStr.isEmpty()) {
result = originalStr;
} else {
final String first = originalStr.substring(0, splitIndex).toLowerCase(
locale);
final String rest = originalStr.substring(splitIndex);
final StringBuilder uncapStr = new StringBuilder(first).append(rest);
result = uncapStr.toString();
}
return result;
}
UPDATE:例として、ロケール設定がトルコ語とドイツ語で小文字のI
を使用することの重要性を示します。
System.out.println(uncapitalize("I", new Locale("TR","tr")));
System.out.println(uncapitalize("I", new Locale("DE","de")));
2つの異なる結果を出力します。
私
私
Javaの文字列は不変なので、どちらの方法でも新しい文字列が作成されます。
最初の例は、一時的な文字配列ではなく、新しい文字列を作成するだけでよいため、おそらくわずかに効率的です。
必要なものをアーカイブするための非常に短く簡単な静的メソッド:
public static String decapitalizeString(String string) {
return string == null || string.isEmpty() ? "" : Character.toLowerCase(string.charAt(0)) + string.substring(1);
}
必要なものが非常に単純な場合(例:Javaクラス名、ロケールなし)、 CaseFormatGoogle Guava ライブラリのクラス。
String converted = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, "FooBar");
assertEquals("fooBar", converted);
または、コンバータオブジェクトを準備して再利用することもできますが、これはより効率的です。
Converter<String, String> converter=
CaseFormat.UPPER_CAMEL.converterTo(CaseFormat.LOWER_CAMEL);
assertEquals("fooBar", converter.convert("FooBar"));
Google Guava文字列操作の哲学をよりよく理解するには、 このwikiページ をチェックしてください。
私は今日だけこれに出くわしました。最も歩行者的な方法でそれを自分でやろうとしました。それには長い行が必要でした。ここに行く
String str = "TaxoRank";
System.out.println(" Before str = " + str);
str = str.replaceFirst(str.substring(0,1), str.substring(0,1).toLowerCase());
System.out.println(" After str = " + str);
与える:
Str = TaxoRanksの前
Str = taxoRanksの後
String testString = "SomeInputString";
String firstLetter = testString.substring(0,1).toLowerCase();
String restLetters = testString.substring(1);
String resultString = firstLetter + restLetters;
val str = "Hello"
s"${str.head.toLower}${str.tail}"
結果:
res4: String = hello