Заменить первую букву строки в Java? - PullRequest
9 голосов
/ 15 марта 2010

Я пытаюсь преобразовать первую букву строки в нижний регистр.

value.substring(0,1).toLowerCase() + value.substring(1)

Это работает, но есть ли лучшие способы сделать это?

Я мог бы использовать функцию замены, но замена Java не принимает индекс. Вы должны передать фактический символ / подстроку. Это можно сделать так:

value.replaceFirst(value.charAt(0), value.charAt(0).toLowerCase())

За исключением того, что replaceFirst ожидает 2 строки, поэтому value.charAt(0) s, вероятно, придется заменить на value.substring(0,1).

Есть ли какой-нибудь стандартный способ заменить первую букву строки?

Ответы [ 4 ]

12 голосов
/ 15 марта 2010

Я бы посоветовал вам взглянуть на библиотеку Commons-Lang от Apache. У них есть класс

StringUtils

, что позволяет вам выполнять множество задач со строками. В вашем случае просто используйте

StringUtils.uncapitalize( value )

читайте здесь о некапитализации , а также о других функциональных возможностях предложенного класса

Добавлено: Мой опыт показывает, что Coomon-Lang довольно хорошо оптимизирован, поэтому, если вы хотите узнать, что лучше с алгоритмической точки зрения, вы можете взглянуть на его источник из Apache. *

3 голосов
/ 15 марта 2010

Недостатком кода, который вы использовали (и я использовал в подобных ситуациях), является то, что он кажется немного неуклюжим и теоретически генерирует как минимум две временные строки, которые сразу выбрасываются. Также возникает вопрос, что произойдет, если длина вашей строки не превышает двух символов.

Положительным моментом является то, что вы не ссылаетесь на эти временные строки вне выражения (оставляя его открытым для оптимизации компилятором байт-кода или оптимизатором 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. : -)

Итак: я бы пошел с вашим простым, понятным кодом, обернутым в служебную функцию.

1 голос
/ 15 марта 2010

Использование StringBuffer:

buffer.setCharAt(0, Character.toLowerCase(buffer.charAt(0)));
1 голос
/ 15 марта 2010

Остерегайтесь любых символьных функций в строках. Из-за юникода это не всегда отображение 1: 1. Придерживайтесь строковых методов, если char действительно не то, что вы хотите Как и предполагали другие, есть строковые утилиты, но даже если вы не хотите использовать их для своего проекта, просто создайте их самостоятельно, пока вы работаете. Худшее, что вы можете сделать, - это создать специальную функцию для строчных букв и скрыть ее в классе, а затем использовать один и тот же код немного по-разному в 12 разных местах. Поместите это куда-нибудь, которым можно легко поделиться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...