是否可以更快地替换Java String中的方法?

时间:2009-06-18 05:38:03

标签: java replace

replace方法返回一个字符串对象而不是替换给定字符串的内容这一事实有点迟钝(但是当你知道字符串在Java中是不可变的时,这是可以理解的)。通过在某些代码中使用深层嵌套替换,我获得了重大的性能提升。有什么我可以用它来取代它会使它更快吗?

10 个答案:

答案 0 :(得分:21)

这是StringBuilder的意思。如果您要进行大量操作,请在StringBuilder上进行操作,然后在需要时将其转换为String

因此描述了

StringBuilder

  

“一个可变的字符序列。此类提供与StringBuffer兼容的API,但不保证同步”。

它有replace(以及appendinsertdelete等等,您可以使用toString将其转换为真实String 1}}。

答案 1 :(得分:8)

之前的帖子是对的,StringBuilder / StringBuffer是一个解决方案。

但是,您还必须质疑在内存中对大字符串进行替换是否是一个好主意。

我经常将String操作实现为流,因此我不是在字符串中替换它然后将其发送到OutputStream,而是在将String发送到输出流时进行替换。这比任何替换都要快得多。

如果您希望此替换实现模板机制,则效果会更快。流式传输总是更快,因为你消耗更少的内存,如果客户端速度慢,你只需要以慢速生成 - 所以它的扩展性要好得多。

答案 2 :(得分:5)

我同意上述内容。使用StringBuffer进行线程安全,使用StringBuilder时使用单线程。

答案 3 :(得分:2)

添加到@paxdiablo答案,这是使用StringBuffers的replaceAll的示例实现,比String.replaceAll()快〜3.7倍:

代码:

public static String replaceAll(final String str, final String searchChars, String replaceChars)
{
  if ("".equals(str) || "".equals(searchChars) || searchChars.equals(replaceChars))
  {
    return str;
  }
  if (replaceChars == null)
  {
    replaceChars = "";
  }
  final int strLength = str.length();
  final int searchCharsLength = searchChars.length();
  StringBuilder buf = new StringBuilder(str);
  boolean modified = false;
  for (int i = 0; i < strLength; i++)
  {
    int start = buf.indexOf(searchChars, i);

    if (start == -1)
    {
      if (i == 0)
      {
        return str;
      }
      return buf.toString();
    }
    buf = buf.replace(start, start + searchCharsLength, replaceChars);
    modified = true;

  }
  if (!modified)
  {
    return str;
  }
  else
  {
    return buf.toString();
  }
}

测试用例 - 输出如下(Delta1 = 1917009502; Delta2 = 7241000026):

@Test
public void testReplaceAll() 
{
  String origStr = "1234567890-1234567890-";

  String replacement1 =  StringReplacer.replaceAll(origStr, "0", "a");
  String expectedRep1 = "123456789a-123456789a-";

  String replacement2 =  StringReplacer.replaceAll(origStr, "0", "ab");
  String expectedRep2 = "123456789ab-123456789ab-";

  String replacement3 =  StringReplacer.replaceAll(origStr, "0", "");
  String expectedRep3 = "123456789-123456789-";


  String replacement4 =  StringReplacer.replaceAll(origStr, "012", "a");
  String expectedRep4 = "1234567890-1234567890-";

  String replacement5 =  StringReplacer.replaceAll(origStr, "123", "ab");
  String expectedRep5 = "ab4567890-ab4567890-";

  String replacement6 =  StringReplacer.replaceAll(origStr, "123", "abc");
  String expectedRep6 = "abc4567890-abc4567890-";

  String replacement7 =  StringReplacer.replaceAll(origStr, "123", "abcdd");
  String expectedRep7 = "abcdd4567890-abcdd4567890-";

  String replacement8 =  StringReplacer.replaceAll(origStr, "123", "");
  String expectedRep8 = "4567890-4567890-";

  String replacement9 =  StringReplacer.replaceAll(origStr, "123", "");
  String expectedRep9 = "4567890-4567890-";

  assertEquals(replacement1, expectedRep1);
  assertEquals(replacement2, expectedRep2);
  assertEquals(replacement3, expectedRep3);
  assertEquals(replacement4, expectedRep4);
  assertEquals(replacement5, expectedRep5);
  assertEquals(replacement6, expectedRep6);
  assertEquals(replacement7, expectedRep7);
  assertEquals(replacement8, expectedRep8);
  assertEquals(replacement9, expectedRep9);

  long start1 = System.nanoTime();
  for (long i = 0; i < 10000000L; i++)
  {
    String rep =  StringReplacer.replaceAll(origStr, "123", "abcdd");
  }
  long delta1 = System.nanoTime() -start1;

  long start2= System.nanoTime();

  for (long i = 0; i < 10000000L; i++)
  {
    String rep =  origStr.replaceAll( "123", "abcdd");
  }

  long delta2 = System.nanoTime() -start1;

  assertTrue(delta1 < delta2);

  System.out.printf("Delta1 = %d; Delta2 =%d", delta1, delta2);


}

答案 4 :(得分:1)

如果要替换多个字符串(例如XML转义序列),特别是在替换与模式长度不同的情况下,FSM词法分析器类型算法似乎最有效,类似于处理的建议流式方式,输出逐步建立。

也许可以使用Matcher对象来有效地做到这一点。

答案 5 :(得分:1)

只需获取char[]的{​​{1}}并进行迭代即可。使用临时String

如果找不到模式,请在迭代时查找要替换的模式,将扫描的内容写入StringBuilder,否则将替换文本写入StringBuilder

答案 6 :(得分:0)

一般来说,所有字符串操作都非常慢。考虑使用StringBuffer,它与String类不完全相同,但有许多共同之处,它也是可变的。

答案 7 :(得分:0)

当您替换单个字符时,请考虑迭代字符数组,但使用(预先创建的)HashMap<Character, Character>()替换字符。

我使用此策略通过unicode上标字符转换整数指数字符串。

String.replace(char, char)相比,速度快了两倍。请注意,与此创建哈希映射关联的时间不包括在此比较中。

答案 8 :(得分:0)

由于String.replace(CharSequence target, CharSequence replacement)内部有Pattern.compilematcherreplaceAll,因此可以通过使用预编译的目标模式常量来对其进行稍微优化,如下所示:

private static final Pattern COMMA_REGEX = Pattern.compile(",");
...
COMMA_REGEX.matcher(value).replaceAll(replacement);

答案 9 :(得分:0)

Apache 公共资源,基于 ERROR TypeError: Cannot read property 'body' of null at IframeContentRender.renderPanel (ej2-richtexteditor.es2015.js:14123)

StringBuilder