Недостатком кода, который вы использовали (и я использовал в подобных ситуациях), является то, что он кажется немного неуклюжим и теоретически генерирует как минимум две временные строки, которые сразу выбрасываются. Также возникает вопрос, что произойдет, если длина вашей строки не превышает двух символов.
Положительным моментом является то, что вы не ссылаетесь на эти временные строки вне выражения (оставляя его открытым для оптимизации компилятором байт-кода или оптимизатором JIT), и ваши намерения ясны для любого будущего сопровождающего кода.
Если вам не нужно делать несколько миллионов из них в любую секунду и , обнаруживая при этом заметную проблему с производительностью, я бы не стал беспокоиться о производительности и предпочел бы ясность. Я также похоронил бы это где-нибудь во вспомогательном классе. :-) См. Также ответ jambjo на другой ответ, указывающий на то, что между String#toLowerCase
и Character.toLowerCase
есть важное различие. ( Edit: ответ и, следовательно, комментарий были удалены. В основном, есть большая разница, связанная с локалями и Unicode, и в документах рекомендуется использовать String#toLowerCase
, а не Character.toLowerCase
; здесь больше . )
Редактировать Поскольку я нахожусь в странном настроении, я подумал, что смогу увидеть измеримую разницу в производительности в простом тесте. Есть. Это может быть из-за различий в локалях (например, яблоки и апельсины):
public class Uncap
{
public static final void main(String[] params)
{
String s;
String s2;
long start;
long end;
int counter;
// Warm up
s = "Testing";
start = System.currentTimeMillis();
for (counter = 1000000; counter > 0; --counter)
{
s2 = uncap1(s);
s2 = uncap2(s);
s2 = uncap3(s);
}
// Test v2
start = System.currentTimeMillis();
for (counter = 1000000; counter > 0; --counter)
{
s2 = uncap2(s);
}
end = System.currentTimeMillis();
System.out.println("2: " + (end - start));
// Test v1
start = System.currentTimeMillis();
for (counter = 1000000; counter > 0; --counter)
{
s2 = uncap1(s);
}
end = System.currentTimeMillis();
System.out.println("1: " + (end - start));
// Test v3
start = System.currentTimeMillis();
for (counter = 1000000; counter > 0; --counter)
{
s2 = uncap3(s);
}
end = System.currentTimeMillis();
System.out.println("3: " + (end - start));
System.exit(0);
}
// The simple, direct version; also allows the library to handle
// locales and Unicode correctly
private static final String uncap1(String s)
{
return s.substring(0,1).toLowerCase() + s.substring(1);
}
// This will *not* handle locales and unicode correctly
private static final String uncap2(String s)
{
return Character.toLowerCase(s.charAt(0)) + s.substring(1);
}
// This will *not* handle locales and unicode correctly
private static final String uncap3(String s)
{
StringBuffer sb;
sb = new StringBuffer(s);
sb.setCharAt(0, Character.toLowerCase(sb.charAt(0)));
return sb.toString();
}
}
Я перепутал порядок в различных тестах (перемещая их и перекомпилируя), чтобы избежать проблем с временем нарастания (и все равно пытался форсировать некоторые). Очень ненаучно, но uncap1
был последовательно медленнее, чем uncap2
и uncap3
примерно на 40%. Не то, чтобы это имело значение, мы говорим о разнице в 400 мс на миллион итераций на процессоре Intel Atom. : -)
Итак: я бы пошел с вашим простым, понятным кодом, обернутым в служебную функцию.