Я протестировал многообещающие подходы, используя 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
был первым подходом Энди и Хлинка:
string = Character.toLowerCase(string.charAt(0)) + string.substring(1);
test2
был вторым подходом Энди. Это также Introspector.decapitalize()
, предложенное Даниэлем, но без двух if
утверждений. Сначала if
был удален из-за предположения о тестировании. Второй был удален, потому что он нарушал правильность (то есть, ввод "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
использовано два substring()
звонка.
string = string.substring(0, 1).toLowerCase() + string.substring(1);
test6
использует отражение для изменения 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
.