【问题标题】:Removing spaces, numbers and special characters from a string从字符串中删除空格、数字和特殊字符
【发布时间】:2021-04-23 21:24:08
【问题描述】:

我正在编写一个函数来从作为参数传递的字符串中删除空格。

此代码有效:

public static String removeSpecialChars(String str) {
    String finalstr = "";
    char[] arr = str.toCharArray();
    char ch;
    for (int i = 0; i < arr.length; i++) {
        ch = arr[i];
        if (Character.isLetter(ch))
            finalstr = finalstr.concat(String.valueOf(ch));
        else
            continue;
    }
    return finalstr;
}

字符串 'hello world!' 的输出如下:

helloworld

但是这个没有:

public static String removeSpecialChars(String str) {
    char[] arr = str.toCharArray();
    char[] arr2 = new char[str.length()];
    char ch;
    for (int i = 0; i < arr.length; i++) {
        ch = arr[i];
        if (Character.isLetter(ch))
            arr2[i] = ch;
    }
    return String.valueOf(arr2);
}

输出:

hello world

我得到与输出相同的字符串,但只删除了感叹号。这可能是什么原因?任何帮助将不胜感激。

【问题讨论】:

  • arr2[i] = ch; 您需要第二个索引(例如int j = 0;)来跟踪将字母添加到新数组的位置。 arr2[j++] = ch;
  • 你可以使用一个简单的正则表达式:return str.replaceAll("[^a-zA-Z]", "");
  • 多项小改进可用: 1) 如果您构建一个字符串,请使用 StringBuilder(快速)或 StringBuffer(线程安全)。这将极大地提高更长(30 多个字符)字符串的速度。 2) 如果您遍历数组的所有元素并且不需要索引,请使用 for-each 循环。因此,不是写for (int i = 0; i &lt; arr.length; i++) {ch=arr[i]; ...},而是在第一个代码示例中写for (char ch: arr) {} 3),而是在循环外定义ch,即使它只在循环内部使用。最好只在循环内定义。 ` { char ch = arr[i];` 更好,防止混淆并释放 varnames
  • arr2 由 (char)0 (\u0000') 字符初始化,对于非字母,这些字符保留在数组中。输出有误导性,因为还有 12 个字符,并且“空格”不是空格 ' '

标签: java arrays string character special-characters


【解决方案1】:

Java 9 开始,您可以使用codePoints 方法:

public static void main(String[] args) {
    System.out.println(removeSpecialChars("hello world!")); // helloworld
    System.out.println(removeSpecialChars("^&*abc123_+"));  // abc
    System.out.println(removeSpecialChars("STRING"));       // STRING
    System.out.println(removeSpecialChars("Слово_Йй+ёЁ"));  // СловоЙйёЁ
}
public static String removeSpecialChars(String str) {
    return str.codePoints()
            // Stream<Character>
            .mapToObj(ch -> (char) ch)
            // filter out non-alphabetic characters
            .filter(Character::isAlphabetic)
            // Stream<String>
            .map(String::valueOf)
            // concatenate into a single string
            .collect(Collectors.joining());
}

另见:How do I count the parentheses in a string?

【讨论】:

    【解决方案2】:

    char 值只是 0 到 2¹⁶−1 范围内的数值。在十六进制(以 16 为底)中,我们将其写为 0000 到 ffff。

    所以,知道每个 char 数组是一个数值序列,让我们看看每个数组在程序运行时的状态。 (为简洁起见,我将每个值显示为两个十六进制数字,而不是四个,因为它们都在 00-ff 范围内。)

    char [] arr = str.toCharArray();
    
    // [ 68 65 6c 6c 6f 20 77 6f 72 6c 64 21 ]
    // (UTF-16 values for the characters in "hello world!")
    
    char [] arr2 = new char[str.length()];
    
    // [ 00 00 00 00 00 00 00 00 00 00 00 00 ]
    // (uninitialized arrays are always initialized with zeroes)
    
    char ch;
    for (int i = 0; i < arr.length; i++) {
        ch = arr[i];
        if (Character.isLetter(ch))
            arr2[i] = ch;
    }
    
    // arr2 after first loop iteration:
    // [ 68 00 00 00 00 00 00 00 00 00 00 00 ]
    
    // arr2 after second loop iteration:
    // [ 68 65 00 00 00 00 00 00 00 00 00 00 ]
    
    // arr2 after third loop iteration:
    // [ 68 65 6c 00 00 00 00 00 00 00 00 00 ]
    
    // arr2 after fourth loop iteration:
    // [ 68 65 6c 6c 00 00 00 00 00 00 00 00 ]
    
    // arr2 after fifth loop iteration:
    // [ 68 65 6c 6c 6f 00 00 00 00 00 00 00 ]
    
    // During sixth loop iteration,
    // the if-condition is not met, so arr2[6]
    // is never changed at all!
    // [ 68 65 6c 6c 6f 00 00 00 00 00 00 00 ]
    
    // arr2 after seventh loop iteration:
    // [ 68 65 6c 6c 6f 00 77 00 00 00 00 00 ]
    
    // During twelfth and final loop iteration,
    // the if-condition is not met, so arr2[11]
    // is never changed at all!
    // [ 68 65 6c 6c 6f 00 77 6f 72 6c 64 00 ]
    

    我不知道你是如何检查返回的字符串的,但实际上是这样的:

    "hello\u0000world\u0000"
    

    正如 Johnny Mopp 指出的那样,由于要跳过一些字符,因此需要使用两个索引变量,并且在最后创建 String 时,需要使用第二个索引变量来限制使用的字符数创建字符串。

    【讨论】:

      猜你喜欢
      • 2021-10-16
      • 2014-08-17
      • 2015-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-16
      • 2020-07-29
      相关资源
      最近更新 更多