Как я могу инвертировать регистр строки в Java?

Я хочу изменить строку так, чтобы все заглавные буквы стали строчными, а все строчные буквы стали заглавными. Числовые символы просто игнорируются.

так "AbCdE123" становится "aBcDe123"

Я предполагаю, что должен быть способ перебирать строку и переворачивать каждый символ или, возможно, какое-нибудь регулярное выражение, которое могло бы это сделать.

 Bart Kiers13 нояб. 2009 г., 16:14
Нет, регулярное выражение не может быть использовано в этом случае.

Ответы на вопрос(8)

что должен быть способ перебрать строку и перевернуть каждый символ

Правильный.java.lang.Character класс предоставляет вам под каждымisUpperCase() метод для этого. Проверьте его и используйтеtoLowerCase() или жеtoUpperCase() методы в зависимости от результата. Добавить результат каждого кStringBuilder и ты должен быть в порядке.

 jarnbjo13 нояб. 2009 г., 18:16
Джон: Если вы соблюдаете правила, специфичные для локали, изменение регистра строки не обязательно сохраняет длину. Например. верхний регистр "ß" является "SS» для немецких языков.
 BalusC14 нояб. 2009 г., 00:10
@jarnbjo: очень хорошее место.
 BalusC13 нояб. 2009 г., 16:15
Тот'действительно выполнимо, если он неНе нужно манипулировать этим потом.
 Jon Skeet13 нояб. 2009 г., 16:13
Нет необходимости добавлять к StringBuilder - вы уже точно знаете, насколько большим будет вывод, и вы можете сделать это в массиве на месте.

так как он имеет методы замены символов. Однако для хранения объекта StringBuilder может потребоваться дополнительное пространство. Таким образом, это поможет, если пространство не имеет значения, и сделает решение простым для понимания.

String swapCase(String text) {
    StringBuilder textSB = new StringBuilder(text);
    for(int i = 0; i < text.length(); i++) {
        if(text.charAt(i) > 64 && text.charAt(i) < 91)
            textSB.setCharAt(i, (char)(text.charAt(i) + 32));
        else if(text.charAt(i) > 96 && text.charAt(i) < 123)
            textSB.setCharAt(i, (char)(text.charAt(i) - 32));
    }
    return textSB.toString();
}
Решение Вопроса

чтобы сделать это (этоотносительно необычно). Это должно сделать это хотя:

public static String reverseCase(String text)
{
    char[] chars = text.toCharArray();
    for (int i = 0; i < chars.length; i++)
    {
        char c = chars[i];
        if (Character.isUpperCase(c))
        {
            chars[i] = Character.toLowerCase(c);
        }
        else if (Character.isLowerCase(c))
        {
            chars[i] = Character.toUpperCase(c);
        }
    }
    return new String(chars);
}

Обратите внимание, что это несделать специфичное для локали изменение, которое делает String.toUpperCase / String.toLowerCase. Это также неt обрабатывать символы не-BMP.

 Sam Barnum13 нояб. 2009 г., 17:19
Это быстро превращается в педантичность, во всяком случае, это был тот случай, когда вызов StringBuffer.toString () будет повторно использовать массив char [], вызывая приватный конструктор пакета String. Я только что проверил, и этобольше не бывает в 1.5+, StringBuilder и StringBuffer 'Методы toString копируют массив char. В любом случае, мне нравится подход char [] лучше.
 Sam Barnum13 нояб. 2009 г., 17:20
Правильно, Джон, отредактировал мой комментарий.
 jarnbjo13 нояб. 2009 г., 17:26
Sam: String (Buffer | Builder) .toString также должен был создать копию в более ранних версиях Java, поскольку изменения в StringBuffer не могут привести к изменениям ранее созданных экземпляров String.
 Jacob Mattison13 нояб. 2009 г., 16:25
На самом деле это почти точно то, что делает код Apache Commons StringUtils, за исключением того, что они используют charAt () для получения каждого символа вместо преобразования в массив и из него. Кроме того, они также проверяют isTitleCase () (и конвертируют в более низкое значение).
 Jon Skeet13 нояб. 2009 г., 16:30
@JacobM: Как они строят массив в конце? Я считаю, что переход к массиву символов, изменение на месте и затем создание строки в конце - один из наиболее эффективных способов выполнения такой работы.
 Jon Skeet13 нояб. 2009 г., 16:42
Используя StringBuffer вместо StringBuilder, ониВы уже понесли (небольшой) штраф за синхронизацию при каждой операции. То есть's внутренняя уборка для StringBuffer, сохранение длины в зависимости от емкости и т. д.я не говорю этобольшая разница - но в обоих случаяхбудет сделана дополнительная (неизбежная) дополнительная копия, и я могуНе вижу никаких реальных преимуществ для подхода StringBuffer.
 Sam Barnum13 нояб. 2009 г., 18:56
@jambjo: В версии 1.4 StringBuffer.toString () вызывал new String (this), который ссылался на исходный массив char [], и вызывал setShared (true) для StringBuffer. Любые дальнейшие изменения в "общий" StringBuffer вызвал StringBuffer 's char [] массив, который нужно скопировать, и сбросьте "общий" флаг. Это больше не относится к версии 1.5+, может быть потому, чтоболее важно быстро добавлять вещи в StringBuffers и StringBuilders, не проверяя,передается для каждой операции записи.
 Jon Skeet13 нояб. 2009 г., 17:14
@ Сэм: Это может зависеть от версии Java, которую выиспользовать, но в исходном коде яя смотрю прямо сейчас (я считаю, 1.6), StringBuffer.toString () используетpublic String(char[], int, int) конструктор, который копирует массив. (Любой публичный конструктор, конечно, должен будет скопировать массив.)
 Jacob Mattison13 нояб. 2009 г., 16:38
Похоже, они начинают с выделения StringBuffer и добавления каждого преобразованного символа в буфер. Наверное, тогда вопрос в том, является ли StringBuffer.toString более или менее эффективным, чем новая строка (char []). Я не могне могу сказать вам. Исходный код доступен наkickjava.com/src/org/apache/commons/lang/StringUtils.java.htm

По мотивам ФаразьПри таком подходе я думаю, что преобразование символов может быть простым:

t += Character.isUpperCase(c) ? Character.toLowerCase(c) : Character.toUpperCase(c);

swapCase метод.

 Trick13 нояб. 2009 г., 16:11
Их StringUtils - один из лучших инструментов для работы со строками.
 Daniel Schneller13 нояб. 2009 г., 16:21
Можно было бы возразить против добавления зависимости в большую библиотеку только для одной функции очень ограниченной сложности.
 skaffman13 нояб. 2009 г., 16:16
+1 за здравый смысл
 Jacob Mattison13 нояб. 2009 г., 19:39
Также добавим, что есть преимущества в использовании подхода, который, как известно, подвергается тщательной проверке и широко используется, например, Apache Commons. Если вы внедрили его самостоятельно, ваш базовый алгоритм мог бы быть в порядке, но (если вы не заставите Джона Скита написать его для вас) у вас может быть небольшая ошибка типа «один на один» или что-то подобное, что победит ».не включайся позже.
 Jacob Mattison13 нояб. 2009 г., 16:22
Договорились о зависимости, но если вы посмотрите вокруг себяВозможно, я найду другие места, где код Commons может упростить ваш код.

Java 8 и выше:

System.out.println(myString.chars().map(c -> Character.isLetter(c) ? c ^ ' ' : c).collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString());

Код, который инвертирует регистр букв, важно заметить:

Character.isLetter(c) ? c ^ ' ' : c

что данный поток очень старый, но есть лучший способ его решить:

class Toggle
{ 
    public static void main()
    { 
        String str = "This is a String";
        String t = "";
        for (int x = 0; x < str.length(); x++)
        {  
            char c = str.charAt(x);
            boolean check = Character.isUpperCase(c);
            if (check == true)
                t = t + Character.toLowerCase(c);
            else
                t = t + Character.toUpperCase(c);
        }
        System.out.println (t);
    }
}
 DrKoch27 янв. 2015 г., 18:39
Пожалуйста, улучшите процесс вспенивания: правильные отступы ...
 RobIII27 янв. 2015 г., 18:40
Не могли бы вы объяснить, почему это так?лучше"? Это'с (функционально) не очень отличаетсяуже принятый ответ, Однако вы не используете массив фиксированной длины или построитель строк, поэтому ваше решение в этом смысле еще хуже ».причина гораздо большего (пере) распределения требуется. Другое дело, что тызаново вводим переменнуюcheck что, по крайней мере, не очень описательно. Также; Это'Это вопрос стиля / вкуса, но если бы это зависело от меня, я быпросто напишуif (Character.isUpperCase(c)) вместо первого назначенияcheck а затем проверка переменной ...
public class ReverseCase {
    public  static void main(String[] args){ 
        char[] char_arr = args[0].toCharArray();
        for (int i = 0; i < char_arr.length; i++) {
            if (Character.isLowerCase(char_arr[i])) {
                char_arr[i] = Character.toUpperCase(char_arr[i]);
            }else {
                char_arr[i] = Character.toLowerCase(char_arr[i]);
            }
        }
        String reversed = new String(char_arr);
        System.out.println(reversed);
    }
}

Ваш ответ на вопрос