Gelecek vaat eden yaklaşımları JMH kullanarak test ettim . Tam karşılaştırma kodu .
Testler sırasında varsayım (her seferinde köşe durumlarını kontrol etmekten kaçınmak için): giriş Dize uzunluğu her zaman 1'den büyüktür.
Sonuçlar
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
Skor saniye başına işlemdir, ne kadar çoksa o kadar iyidir.
Testler
test1
ilk olarak Andy ve Hllink'in yaklaşımıydı:
string = Character.toLowerCase(string.charAt(0)) + string.substring(1);
test2
Andy'nin ikinci yaklaşımı oldu. Introspector.decapitalize()
Daniel tarafından da önerildi, ancak iki if
açıklama yapılmadı . İlk if
olarak test varsayımı nedeniyle kaldırıldı. İkincisi, doğruluğu ihlal ettiği için kaldırıldı (yani girdi "HI"
geri dönecekti "HI"
). Bu neredeyse en hızlıydı.
char c[] = string.toCharArray();
c[0] = Character.toLowerCase(c[0]);
string = new String(c);
test3
bir modifikasyondu test2
, ancak bunun yerine Character.toLowerCase()
32 ekliyordum, bu sadece ve ancak dizge ASCII'de ise doğru çalışıyor. Bu en hızlıydı. c[0] |= ' '
Mike'ın yorumundan aynı performansı verdi.
char c[] = string.toCharArray();
c[0] += 32;
string = new String(c);
test4
kullanılmış StringBuilder
.
StringBuilder sb = new StringBuilder(string);
sb.setCharAt(0, Character.toLowerCase(sb.charAt(0)));
string = sb.toString();
test5
iki substring()
çağrı kullandı .
string = string.substring(0, 1).toLowerCase() + string.substring(1);
test6
char value[]
doğrudan String'de değiştirmek için yansıma kullanır . Bu en yavaş olanıydı.
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();
}
Sonuçlar
Dize uzunluğu her zaman 0'dan büyükse, kullanın test2
.
Değilse, köşe durumlarını kontrol etmeliyiz:
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);
}
Metninizin her zaman ASCII'de olacağından eminseniz ve bu kodu darboğazda bulduğunuz için aşırı performans arıyorsanız, kullanın test3
.