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

huangapple go评论76阅读模式
英文:

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

问题

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;
}
英文:

I wanted to create a method that reverse upper-lower case letters in a word. The problem I'm having is that the method doesn't reverse all the letters. For example when I type "nIceToMeEtyoU" it prints "NiCETomEETYou". It didn't work for the "o", the second "e" and "t". I just couldn't figure out what's wrong with the code.

public static String reverseCase(String str) {
	char changed;
	String a = str;
	for (int i = 0; i &lt; 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;
}

答案1

得分: 2

String::replace返回一个新的字符串,其中包含你想要替换的字符的所有出现被改变。

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

英文:

String::replace returns a new String with all occurrences of the character you wanted replaced changed.

Also, Strings in Java are immutable, meaning you cannot replace a character in a string while keeping the same string.
In order to replace the character at a specific index, see this post

答案2

得分: 2

它对于 "o"、"第二个e" 和 "t" 没有起作用。

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

相反,使用 StringBuffer 在迭代字符串时逐个添加每个字符。

然后在循环结束时,使用 StringBuffer 的 toString() 方法重新创建字符串。

英文:

> It didn't work for the "o","second e" and "t".

The replace() method replaces all occurrances of the character in the string.

Instead, use a StringBuffer to append each character as you iterate through the string.

Then when the loop is finished you recreate the String using the toString() method of the StringBuffer.

答案3

得分: 2

代替使用String#replace,后者会将所有匹配的实例替换为给定的替换内容,我建议您使用StringBuilder来构建字符串,如下所示:

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

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

        // 使用增强型for循环
        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

根据您的方法,无论在一次遍历中更改了哪些字符,如果在后续遍历中再次找到它们,它们将在下一次遍历中被恢复。

英文:

Instead of using String#replace which replaces all instances of the match with the given replacement, I suggest you build the string using a StringBuilder as shown below:

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

	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();
	}
}

Output:

NiCEtOmEeTYOu
nIcetOMeetyOU

With your approach, whichever characters are being changed in one pass, will get reverted back in the next passes if they are found again in those passes.

答案4

得分: 1

replace函数会替换字符串中所有出现的字符。例如,第一次遇到字符e时,将会将所有的e替换为E。接着,下一次遇到经过替换的“原始”e(现在是E)时,所有的E都会被重新替换为e,依此类推。

你可以不使用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 = str.charAt(i);
        if (Character.isUpperCase(c)) {
            c = Character.toLowerCase(c);
        } else if (Character.isLowerCase(c)) {
            c = Character.toUpperCase(c);
        }
        sb.append(c);
    }
    return sb.toString();
}
英文:

replace replaces all occurrences of a character in a string. So, e.g., the first time you encounter e you'll replace all the es with Es. Then, the when next "original" e (which is now an E) is encountered, all Es will be turned back to es and so on.

Instead of using replace, you could accumulate the characters you encounter in a new object. While you could use a String and add to it with the += operator, using a StringBuilder should have better performance:

public static String reverseCase(String str) {
    StringBuilder sb = new StringBuilder(str.length());
    for (int i = 0; i &lt; 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();
}

答案5

得分: 1

代替使用 replace(它会替换字符串中的所有出现),你可以将每个字符连接起来以创建一个新的字符串。

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();
}
英文:

Instead of using replace (which replaces all the occurrences in the string) you can concat each character to create a new string.

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();
}

答案6

得分: 1

你可以使用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"));
}
英文:

You could StringBuilder for String operations which is not accessed by other threads. The main issue you are facing here is because of the replace() method as mentioned by others. The replace() method replaces all occurrances of the character in the string. Instead of trying to replace, just build new string and return.
Another way you could do it is to create an array of characters and replace the character (with the variable : 'changed') at the current position inside the loop.

public static String reverseCase(String str) {
		char changed;
		StringBuilder reversedStringBuilder=new StringBuilder();
		for (int i = 0; i &lt; 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(&quot;nIceToMeEtyoU&quot;));
	}

答案7

得分: 1

a.replace(d, changed)会替换字符串中每一个出现的d,而不仅仅是在你查看的索引位置上的一个。

  • 所以对于字符串中每个出现偶数次的字母,对该字母的替换会被执行偶数次,保留所有出现的情况与最初第一次出现时的大小写相同。这就是发生在 o 的情况。当你遇到第一个 o 时,两个出现都被替换为大写的 O。当你遇到下一个 O 时,它已经是大写的,所以两个出现都被改回小写。
  • 相反,如果一个字母出现奇数次,它会经过相同的过程,最终保留与最初第一次出现时相反大小写的状态。一开始你有两个小写的 e 和一个大写的 E。首先,两个小写的 e 被改为大写。其次,所有三个都被改为小写。第三,全部改为大写。

因此,不要直接在字符串中执行替换操作。可以使用 StringBufferStringBuilderchar 数组。在这些数据结构中,可以根据索引执行替换,以便只影响到你打算修改的字母出现的位置。

额外提示:if (letter == true) 被认为是一种一般的写法风格。最好只使用 if (letter)

额外信息:存在一些字母在切换大小写时会变成多个字母。如果我输入德语单词 F&#252;&#223;efeet,意为“脚”),&#223; 只存在于小写情况下,变成大写后会变成 SS。因此,该词的正确反向应该是 f&#220;SSE。然而,Character.toUpperCase() 无法返回两个字符,所以只会保留为 &#223;

英文:

a.replace(d, changed) replaces every occurrence of d in the string, not just the one at the index you are looking at.

  • So for every letter that occurs an even number of times in the string, the replace of that letter is performed an even number of times, leaving all occurrences at the same case that the first occurrence had from the outset. This was what happened to o, for example. When you met the first o, both occurrences were replaced to upper case O. When you met the next O, it was already upper case, so both occurrences were changed to lower case again.
  • Conversely if a letter occurs an odd number of times, it will through the same procedure be left at the opposite case of what the first occurrence had from the outset. From the outset you had e twice and E once. First the two lower case e were changed to upper case. Second alll three were changed to lower case. Third, all to upper case.

Instead do not perform the replacements directly in the string. Use either a StringBuffer or StringBuilder or a char array. In each of these you can perform the replacement by index so that you are only affecting the occurrence of the letter that you intend to affect.

Bonus tip: if (letter == true) is considered mediocre style. Prefer just if (letter).

Bonus information: Letters exist that become more than one letter when switching case. If I enter the German word F&#252;&#223;e (feet), &#223; only exists in lower case, it becomes SS in upper case. So the correct reverse of the word would be f&#220;SSE. However, Character.toUpperCase() cannot return two chars, so just leaves it at &#223;.

答案8

得分: 1

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
    }
}
英文:

Using Streams

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 -&gt; (char) i)
                .map(ch -&gt; String.valueOf(FlipCase.flipCase(ch)))
                .collect(Collectors.joining());
    }

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

答案9

得分: 1

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

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

您可以通过将大写字母的位与小写字母的位进行翻转来实现。

关键是要知道从右边数第六位是在 Strings(就像您的示例中一样)的情况下连接大小写的位。这将是从第 5 位开始的第 2 位,即 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()) {
       // 如果是字母则改变大小写
       sb.append(Character.isLetter(c) ? (char) (c ^ 32) : c);
   }
   return sb.toString();
}

输出

NiCEtOmEeTYOu
英文:

As has been stated, the issue is the replace. Best to use a StringBuilder and create a new String.

I also offer an alternative that you may find interesting.

You can do it by flipping the bit from upper case to lower case and visa versa.

The key is knowing that the sixth bit from the right is the bit between cases for Strings (as in your example). That would be 2 to the 5th or 32. The Exclusive OR operator (^) can be used to flip the bit.

String s = &quot;nIceToMeEtyoU&quot;;
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();
}

Prints

NiCEtOmEeTYOu

</details>



# 答案10
**得分**: 1

```plaintext
你之前尝试过[Apache Commons][1]吗?我确信这是处理这种情况最简单的方法:

    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

  [1]: https://www.javacodeexamples.com/apache-commons-tutorial-with-examples/1588
英文:

Did you try Apache Commons before? I'm sure that it is the most simple way to handle this case:

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

And the output will be:

tHEmosTSIMplewaYTOSWApcase

huangapple
  • 本文由 发表于 2020年9月19日 22:25:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/63969822.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定