繁体   English   中英

反转大小写的Java方法不会反转所有字母

[英]Java method to reverse upper-lower case doesn't reverse all letters

我想创建一种方法来反转单词中的大写字母。 我遇到的问题是该方法不会反转所有字母。 例如,当我输入“nIceToMeEtyoU”时,它会打印“NiCETomEETYou”。 它不适用于“o”、第二个“e”和“t”。 我只是无法弄清楚代码有什么问题。

public static String reverseCase(String str) {
    char changed;
    String a = str;
    for (int i = 0; i < a.length(); i++) {
        char d = a.charAt(i);
        boolean letter = Character.isUpperCase(d);
        if (letter == true) {
            changed = Character.toLowerCase(d);
        } else {
            changed = Character.toUpperCase(d);
        }
        a = a.replace(d, changed);
    }
    return a;
}

String::replace返回一个新字符串,其中所有出现的要替换的字符都已更改。

此外,Java 中的字符串是不可变的,这意味着您不能在保持相同字符串的同时替换字符串中的字符。 为了替换特定索引处的字符,请参阅此帖子

它不适用于“o”、“second e”和“t”。

replace() 方法替换字符串中所有出现的字符。

相反,当您遍历字符串时,使用StringBuffer来附加每个字符。

然后当循环完成时,您使用StringBuffer的 toString() 方法重新创建 String 。

我建议您使用StringBuilder构建字符串,而不是使用String#replace将匹配的所有实例替换为给定的替换,如下所示:

public class Main {
    public static void main(String[] args) {
        // Tests
        System.out.println(reverseCase("nIceToMeEtyoU"));
        System.out.println(reverseCase("NiCETomEETYou"));
    }

    public static String reverseCase(String str) {
        StringBuilder sb = new StringBuilder();

        // Use the enhanced for loop
        for (char ch : str.toCharArray()) {
            if (Character.isUpperCase(ch)) {
                ch = Character.toLowerCase(ch);
            } else {
                ch = Character.toUpperCase(ch);
            }
            sb.append(ch);
        }
        return sb.toString();
    }
}

输出:

NiCEtOmEeTYOu
nIcetOMeetyOU

使用您的方法,无论在一次传递中更改哪个字符,如果在这些传递中再次找到它们,都将在下一次传递中恢复。

replace替换字符串中所有出现的字符。 因此,例如,当您第一次遇到e您会将所有的e替换为E 然后,当遇到下一个“原始” e (现在是E )时,所有E s 将变回e s ,依此类推。

您可以在新对象中累积遇到的字符,而不是使用replace 虽然您可以使用String并使用+=运算符添加到它,但使用StringBuilder应该具有更好的性能:

public static String reverseCase(String str) {
    StringBuilder sb = new StringBuilder(str.length());
    for (int i = 0; i < str.length(); i++) {
        char c = a.charAt(i);
        id (Character.isUpperCase(c) {
            c = Character.toLowerCase(c);
        } else i (Character.isLowerCase(c)) {
            c = Character.toLowerCase(c);
        }
        sb.append(c);
    }
    return st.toString();
}

您可以连接每个字符以创建一个新字符串,而不是使用替换(替换字符串中的所有出现)。

public static String reverseCase(String input) {
    StringBuilder a = new StringBuilder();
    for (char c : input.toCharArray()) {
      a.append(Character.isUpperCase(c) ? Character.toLowerCase(c) : Character.toUpperCase(c));
    }
    return a.toString();
}

您可以将 StringBuilder 用于其他线程无法访问的字符串操作。 您在这里面临的主要问题是因为其他人提到的 replace() 方法。 replace() 方法替换字符串中所有出现的字符。 而不是尝试替换,只需构建新字符串并返回。 另一种方法是创建一个字符数组并替换循环内当前位置的字符(使用变量:'changed')。

public static String reverseCase(String str) {
        char changed;
        StringBuilder reversedStringBuilder=new StringBuilder();
        for (int i = 0; i < str.length(); i++) {
            char d = str.charAt(i);
            boolean letter = Character.isUpperCase(d);
            if (letter) {
                changed = Character.toLowerCase(d);
            } else {
                changed = Character.toUpperCase(d);
            }
            reversedStringBuilder.append(changed);
        }
        return reversedStringBuilder.toString();
    }
    
    public static void main(String[] args) {
        System.out.println(reverseCase("nIceToMeEtyoU"));
    }

a.replace(d, changed)替换字符串中出现的每个d ,而不仅仅是您正在查看的索引处的那个。

  • 因此,对于字符串中出现偶数次的每个字母,该字母的替换执行偶数次,使所有出现的情况与第一次出现的情况相同。 例如,这就是o发生的事情。 当您遇到第一个o ,两个出现都被替换为大写O 当你遇到下一个O ,它已经是大写了,所以两个出现的地方又变成了小写。
  • 相反,如果一个字母出现奇数次,它将通过相同的程序保留在与第一次出现从一开始就出现的情况相反的情况。 从一开始,你有两次e和一次E 首先将两个小写的e改为大写。 其次,所有三个都改为小写。 第三,全部为大写。

相反,不要直接在字符串中执行替换。 使用StringBufferStringBuilderchar数组。 在其中的每一个中,您都可以按索引执行替换,以便您只影响您打算影响的字母的出现。

额外提示: if (letter == true)被认为是平庸的风格。 更喜欢if (letter)

奖励信息:存在在切换大小写时变成多个字母的字母。 如果我输入德语单词Füße ( feet ),则ß仅以小写形式存在,而在大写形式中变为SS 所以这个词的正确fÜSSE应该是fÜSSE 但是, Character.toUpperCase()不能返回两个字符,所以将它留在ß

使用流

import java.util.stream.Collectors;

public class FlipCase {

    static char flipCase(char ch) {
        if (Character.isUpperCase(ch)) return Character.toLowerCase(ch);
        else return Character.toUpperCase(ch);
    }

    public static String reverseCase(String str) {
        return str
                .chars()
                .mapToObj(i -> (char) i)
                .map(ch -> String.valueOf(FlipCase.flipCase(ch)))
                .collect(Collectors.joining());
    }

    public static void main(String[] args) {
        System.out.println(reverseCase("nIceToMeEtyoU")); // NiCEtOmEeTYOu
    }
}

如前所述,问题是replace 最好使用StringBuilder并创建一个新字符串。

我还提供了一个您可能会感兴趣的替代方案。

您可以通过将位从大写翻转到小写来实现,反之亦然。

关键是要知道右起第六位是Strings案例之间的位(如您的示例)。 那将是 2 到 5 或 32。异或运算符 ( ^ ) 可用于翻转位。

String s = "nIceToMeEtyoU";
System.out.println(reverseCase(s));
    
public static String reverseCase(String s) {
   StringBuilder sb = new StringBuilder(s.length());
   for(char c : s.toCharArray()) {
       // change the case if letter
       sb.append(Character.isLetter(c) ? (char) (c ^ 32) : c);
   }
   return sb.toString();
}

印刷

NiCEtOmEeTYOu

您之前尝试过Apache Commons吗? 我确信这是处理这种情况的最简单方法:

package com.awm4n.swapcaseexample;
import org.apache.commons.lang3.StringUtils;
public class SwapCaseExample {
    public static void main(String[] args) {
        String str = "TheMOStsimPLEWAytoswaPCASE";            
        System.out.println( StringUtils.swapCase(str) );
    }
}

输出将是:

tHEmosTSIMplewaYTOSWApcase

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM