StringBuilder vs. String 正在考虑替换

2022-09-01 07:33:51

在连接大量字符串时,我被建议使用这样的:StringBuilder

StringBuilder someString = new StringBuilder("abc");
someString.append("def");
someString.append("123");
someString.append("moreStuff");

String someString = "abc";
someString = someString + "def";
someString = someString + "123";
someString = someString + "moreStuff";

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

现在,我需要做一个类似的事情,但不是使用串联,而是使用String的方法:replace

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");

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

someString.replace(someString.indexOf("$VARIABLE1"), someString.indexOf("$VARIABLE1")+10, "abc");

所以我的问题是:“是使用String.replace并创建大量额外的字符串更好,还是仍然使用StringBuilder,并且有很多长长的行,如上面的那个?


答案 1

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

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

String result = someString + someOtherString + anotherString;

变成这样:

String result = new StringBuilder().append(someString).append(someOtherString).append(anotherString).toString();

也就是说,除非你要替换大量的字符串,否则请选择更具可读性和可维护性的任何字符串。因此,如果您可以通过一系列“替换”调用来使其更干净,请继续通过StringBuilder方法执行此操作。与你从处理微优化的悲惨悲剧中节省的压力相比,这种差异可以忽略不计。

附言

对于您的代码示例(正如 OscarRyz 所指出的,如果您在 中有多个代码示例,则代码示例将不起作用,在这种情况下,您需要使用循环),您可以将调用结果缓存在:"$VARIABLE1"someStringindexOf

someString.replace(someString.indexOf("$VARIABLE1"), someString.indexOf("$VARIABLE1")+10, "abc");

int index = someString.indexOf("$VARIABLE1");    
someString.replace(index, index+10, "abc");

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


答案 2

你猜怎么着?如果您使用 Java 1.5+ 运行,则串联的工作方式与字符串文本相同

  String h = "hello" + "world";

  String i = new StringBuilder().append("hello").append("world").toString();

都是一样的。

因此,编译器已经为您完成了这项工作。

当然,更好的是:

 String j = "hellworld"; // ;) 

至于第二个,是的,这是首选,但不应该那么难,具有“搜索和替换”的力量和一些正则表达式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 );
    }
  }

您的代码当前如下所示:

someString = someString.replace("VARIABLE1", "abc");
someString = someString.replace("VARIABLE2", "xyz");

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

%s/^.*("\(.*\)".\s"\(.*\)");/replace("\1","\2",builder);

上面写着:“在括号中取任何东西,看起来像一个字符串文本,然后把它放在另一个字符串中”。

你的代码将从这里看:

someString = someString.replace("VARIABLE1", "abc");
someString = someString.replace("VARIABLE2", "xyz");

对此:

replace( "VARIABLE1", "abc", builder );
replace( "VARIABLE2", "xyz", builder );

立刻。

这是一个工作演示:

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