Saya menguji pendekatan yang menjanjikan menggunakan JMH . Kode benchmark lengkap .
Asumsi selama pengujian (untuk menghindari pemeriksaan kasus sudut setiap saat): panjang string input selalu lebih besar dari 1.
Hasil
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
Skornya adalah operasi per detik, semakin banyak semakin baik.
Tes
test1 adalah pendekatan Andy dan Hllink pertama:
string = Character.toLowerCase(string.charAt(0)) + string.substring(1);
test2adalah pendekatan Andy kedua. Ini juga Introspector.decapitalize()dikemukakan oleh Daniel, tetapi tanpa dua ifpernyataan. Pertama ifdihapus karena asumsi pengujian. Yang kedua telah dihapus, karena melanggar kebenaran (yaitu, masukan "HI"akan kembali "HI"). Ini hampir yang tercepat.
char c[] = string.toCharArray();
c[0] = Character.toLowerCase(c[0]);
string = new String(c);
test3adalah modifikasi dari test2, tetapi alih-alih Character.toLowerCase(), saya menambahkan 32, yang berfungsi dengan benar jika dan hanya jika string ada dalam ASCII. Ini yang tercepat. c[0] |= ' 'dari komentar Mike memberikan penampilan yang sama.
char c[] = string.toCharArray();
c[0] += 32;
string = new String(c);
test4bekas StringBuilder.
StringBuilder sb = new StringBuilder(string);
sb.setCharAt(0, Character.toLowerCase(sb.charAt(0)));
string = sb.toString();
test5menggunakan dua substring()panggilan.
string = string.substring(0, 1).toLowerCase() + string.substring(1);
test6menggunakan refleksi untuk mengubah char value[]secara langsung dalam String. Ini yang paling lambat.
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();
}
Kesimpulan
Jika panjang String selalu lebih besar dari 0, gunakan test2.
Jika tidak, kami harus memeriksa kasus sudut:
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);
}
Jika Anda yakin bahwa teks Anda akan selalu dalam ASCII dan Anda mencari kinerja ekstrim karena Anda menemukan kode ini di kemacetan, gunakan test3.