【问题标题】:java: what's the most efficient way to remove all blank space from a StringBuilderjava:从StringBuilder中删除所有空格的最有效方法是什么
【发布时间】:2012-04-23 05:52:36
【问题描述】:

我是通过下面的代码实现的,但是不知道有没有更有效的方法可以去除StringBuilder中的所有空格

private static StringBuilder removeBlankSpace(StringBuilder sb){
    for(int i=0;i<sb.length();++i){
        if(Character.isWhitespace(sb.charAt(i))){
            sb.deleteCharAt(i);
                            i--;
        }
    }
    return sb;
}

【问题讨论】:

  • 您应该在您的函数中创建新的 StringBuilder 并复制所有非空白字符。方法 deleteCharAt 删除一个字符并移动 char 数组的其余部分。方法不应该修改输入参数!!!

标签: java


【解决方案1】:

您不应多次调用delete - 只需将每个字符向下移动到其最终位置,然后删除末尾的范围即可。

static void removeBlankSpace(StringBuilder sb) {
  int j = 0;
  for(int i = 0; i < sb.length; i++) {
    if (!Character.isWhitespace(sb.charAt(i))) {
       sb.setCharAt(j++, sb.charAt(i));
    }
  }
  sb.delete(j, sb.length);
}

【讨论】:

  • 一个潜在的优化:j 为 0,您只需要检查空格,无需更改任何内容。因此,您可能希望有一个初始循环,直到找到第一个空格,然后是所示方法的其余部分。
  • 当我们关注性能时,在最后使用sb.setLength,而不是sb.delete,可能更有效,或者至少是明确有效的。
  • @Jon:我想你的意思是while j==i
  • 显然在这个解决方案中,我们处理的是方法 length() 而不是 length
【解决方案2】:

编辑:将这个答案留给后代,but Keith Randall's O(n) solution 更好。

您可能会发现从远端开始工作效率更高 - 这样当您删除 early 字符时,您就不会再从后面复制空格了。

另外,如果您的数据往往包含多个空白字符,您可能希望发现这一点并调用delete 而不是deleteCharAt。所以像:

private static StringBuilder removeBlankSpace(StringBuilder sb) {
    int currentEnd = -1;
    for(int i = sb.length() - 1; i >= 0; i--) {
        if (Character.isWhitespace(sb.charAt(i))) {
            if (currentEnd == -1) {
                currentEnd = i + 1;
            }
        } else {
            // Moved from whitespace to non-whitespace
            if (currentEnd != -1) {
                sb.delete(i + 1, currentEnd);
                currentEnd = -1;
            }
        }
    }
    // All leading whitespace
    if (currentEnd != -1) {
        sb.delete(0, currentEnd);
    }
    return sb;
}

【讨论】:

  • 谢谢,但我不知道我为什么要在远端工作,你能详细解释一下吗?
  • @remy:假设你有一个由一个空格组成的字符串,然后是很多非空格,然后是一百万个空格。如果先删除第一个空格,最终会在不需要时复制所有空格。正如我所编辑的,基思的回答要好得多:)
  • 非常感谢您的解释。
【解决方案3】:

以下内容如何(假设您已初始化 StringBuilder sb):

sb = new StringBuilder(sb.toString().replaceAll("\\s", ""));

【讨论】:

  • 这将删除最后一个空格之前的 everything。所以“你好”变成了“那里”。我认为这不是必需的。它还检测空格。
  • 这会起作用(在你逃脱了文字中的反斜杠之后),但它有点违背了从 StringBuilder 开始的意义......
  • @Jon Skeet,你的意思是在性能方面String.replaceAll 比循环遍历StringBuilder 字符更差吗?
  • 我的意思是我怀疑调用toString(),然后调用replaceAll,然后构建一个新的StringBuilder 会更糟。特别是,如果 没有 任何空白字符会无缘无故地进行大量复制。
  • 是的,你是对的 - 没有说明保证。然而,这是一个明显的、自然的、幼稚的实现所给出的,而我不想开始猜测正则表达式的性能。我仍然非常喜欢 Keith 的方法 :)
【解决方案4】:

删除字符串的前导和尾随空格的代码

 int i = 0;
 int j = 0;

 for (; i < whiteSpcaTest.length();) {
   i = 0;
   if (Character.isWhitespace(whiteSpcaTest.charAt(i))) {
     whiteSpcaTest.deleteCharAt(i);

   } else {
     break;
   }
 }
 for (; j >= 0;) {
   j = whiteSpcaTest.length() - 1;
   if (Character.isWhitespace(whiteSpcaTest.charAt(j))) {
     whiteSpcaTest.deleteCharAt(j);

   } else {
     break;
   }

 }

【讨论】:

    【解决方案5】:

    java 字符串 trim() 方法消除了前导和尾随空格。空格字符的 unicode 值为 '\u0020'。 java 字符串中的 trim() 方法检查字符串前后的 unicode 值,如果存在则删除空格并返回省略的字符串。例如:

    public class StringTrimExample{  
    public static void main(String args[]){  
    String s1="  hello string   ";  
    System.out.println(s1+"javatpoint");//without trim()  
    System.out.println(s1.trim()+"javatpoint");//with trim()  
    }}  
    

    结果:

      hello string   javatpoint
    hello stringjavatpoint  
    

    【讨论】:

      猜你喜欢
      • 2019-10-12
      • 2022-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多