StringBuilder与String考虑替换

Dan*_*bbs 32 java string stringbuilder replace

在连接大量字符串时,我建议使用StringBuilder如下方法:

StringBuilder someString = new StringBuilder("abc");
someString.append("def");
someString.append("123");
someString.append("moreStuff");
Run Code Online (Sandbox Code Playgroud)

而不是

String someString = "abc";
someString = someString + "def";
someString = someString + "123";
someString = someString + "moreStuff";
Run Code Online (Sandbox Code Playgroud)

这将导致创建相当多的字符串,而不是一个.

现在,我需要做类似的事情,但我没有使用串联,而是使用replaceString 的方法:

String someString = SOME_LARGE_STRING_CONSTANT;
someString = someString.replace("$VARIABLE1", "abc");
someString = someString.replace("$VARIABLE2", "def");
someString = someString.replace("$VARIABLE3", "123");
someString = someString.replace("$VARIABLE4", "moreStuff");
Run Code Online (Sandbox Code Playgroud)

要使用StringBuilder完成同样的事情,我必须这样做,只为一个替换:

someString.replace(someString.indexOf("$VARIABLE1"), someString.indexOf("$VARIABLE1")+10, "abc");
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:"使用String.replace是否更好,并且创建了大量额外的字符串,或者仍然使用StringBuilder,并且有很多冗长的线条,例如上面那个?"

Zac*_*h L 44

确实,StringBuilder往往比手动连接或修改字符串更好,因为StringBuilder是可变的,而String是不可变的,你需要为每个修改创建一个新的String.

但请注意,Java编译器会自动转换如下示例:

String result = someString + someOtherString + anotherString;
Run Code Online (Sandbox Code Playgroud)

变成这样的东西:

String result = new StringBuilder().append(someString).append(someOtherString).append(anotherString).toString();
Run Code Online (Sandbox Code Playgroud)

也就是说,除非你要替换掉很多字符串,否则请选择更具可读性和更易维护性的字符串.因此,如果您可以通过一系列"替换"调用来保持它更清洁,那么继续执行StringBuilder方法.与处理微观优化的悲惨悲剧所节省的压力相比,差异可以忽略不计.

PS

对于您的代码示例(其中,作为OscarRyz指出,如果你有一个以上的,将无法正常工作"$VARIABLE1"someString,在这种情况下,你需要使用一个循环),你可以缓存的结果indexOf呼叫:

someString.replace(someString.indexOf("$VARIABLE1"), someString.indexOf("$VARIABLE1")+10, "abc");
Run Code Online (Sandbox Code Playgroud)

int index = someString.indexOf("$VARIABLE1");    
someString.replace(index, index+10, "abc");
Run Code Online (Sandbox Code Playgroud)

无需搜索字符串两次:-)


Osc*_*Ryz 7

你猜怎么着?如果您使用的是Java 1.5+,则串联与字符串文字的作用相同

  String h = "hello" + "world";
Run Code Online (Sandbox Code Playgroud)

  String i = new StringBuilder().append("hello").append("world").toString();
Run Code Online (Sandbox Code Playgroud)

是相同的.

所以,编译器已经为你完成了工作.

当然更好的是:

 String j = "hellworld"; // ;) 
Run Code Online (Sandbox Code Playgroud)

至于第二个,是的,这是首选,但不应该那么难,具有"搜索和替换"的力量和一点正则表达式foo

例如,您可以定义一个类似于此示例中的方法:

  public static void replace( String target, String replacement, 
                              StringBuilder builder ) { 
    int indexOfTarget = -1;
    while( ( indexOfTarget = builder.indexOf( target ) ) >= 0 ) { 
      builder.replace( indexOfTarget, indexOfTarget + target.length() , replacement );
    }
  }
Run Code Online (Sandbox Code Playgroud)

您的代码目前看起来像这样:

someString = someString.replace("VARIABLE1", "abc");
someString = someString.replace("VARIABLE2", "xyz");
Run Code Online (Sandbox Code Playgroud)

所有你需要做的就是抓住文本编辑器这样的触发器,如vi搜索和替换:

%s/^.*("\(.*\)".\s"\(.*\)");/replace("\1","\2",builder);
Run Code Online (Sandbox Code Playgroud)

这就是:"在括号中取任何东西,看起来像一个字符串文字,并把它放在另一个字符串中".

您的代码将从以下内容看:

someString = someString.replace("VARIABLE1", "abc");
someString = someString.replace("VARIABLE2", "xyz");
Run Code Online (Sandbox Code Playgroud)

对此:

replace( "VARIABLE1", "abc", builder );
replace( "VARIABLE2", "xyz", builder );
Run Code Online (Sandbox Code Playgroud)

立刻.

这是一个有效的演示:

class DoReplace { 
  public static void main( String ... args ) {
    StringBuilder builder = new StringBuilder(
       "LONG CONSTANT WITH VARIABLE1 and  VARIABLE2 and VARIABLE1 and VARIABLE2");
    replace( "VARIABLE1", "abc", builder );
    replace( "VARIABLE2", "xyz", builder );
    System.out.println( builder.toString() );
  }
  public static void replace( String target, String replacement, 
                              StringBuilder builder ) { 
    int indexOfTarget = -1;
    while( ( indexOfTarget = builder.indexOf( target ) ) > 0 ) { 
      builder.replace( indexOfTarget, indexOfTarget + target.length() , 
                       replacement );
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 实际上,在你的第一个例子中,编译器实际上并不生成StringBuilder解决方案,而是生成第三个代码行,因为它是一个编译时常量.所以这些是等价的. (2认同)