我使用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
分数是每秒的操作数,越多越好。
测试
-
test1
首先是Andy和Hllink的方法:
string = Character.toLowerCase(string.charAt(0)) + string.substring(1);
-
test2
这是安迪的第二种方法。它也是丹尼尔建议的Interspector.deccaptalize(),
但没有两个语句。由于测试假设,第一个被删除了。第二个被删除了,因为它违反了正确性(即输入将返回)。这几乎是最快的。if
if
"HI"
"HI"
char c[] = string.toCharArray();
c[0] = Character.toLowerCase(c[0]);
string = new String(c);
-
test3
是 的修改,但不是 ,我添加了 32,当且仅当字符串采用 ASCII 时,它才能正常工作。这是最快的。 从迈克的评论中给出了相同的表现。test2
Character.toLowerCase()
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
使用了两个调用。substring()
string = string.substring(0, 1).toLowerCase() + string.substring(1);
-
test6
使用反射直接在字符串中更改 char 值 []
。这是最慢的。
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