在Java中执行大量字符串替换的最快方法

我必须编写某种解析器来获取String并用其他字符替换某些字符集。 代码如下所示:

noHTMLString = noHTMLString.replaceAll("

", "\n"); noHTMLString = noHTMLString.replaceAll("
", "\n\n"); noHTMLString = noHTMLString.replaceAll("
", "\n\n"); //here goes A LOT of lines like these ones

该函数非常长并且执行许多字符串替换。 这里的问题是它需要花费很多时间,因为它被称为很多次的方法,从而降低了应用程序的性能。

我在这里阅读了一些关于使用StringBuilder作为替代方案的线程,但它缺少ReplaceAll方法,并且正如此处所述, string.replaceAll()性能是否受到字符串不变性的影响? String类中的replaceAll方法适用于

Match Pattern&Matcher和Matcher.replaceAll()使用StringBuilder存储最终返回的值,因此我不知道切换到StringBuilder是否会真正减少执行替换的时间。

您是否知道以快速方式快速完成大量String替换? 你对这个问题有什么建议吗?

谢谢。

编辑 :我必须创建一个报告,其中包含一些带有html文本的字段。 对于每一行,我正在调用替换这些字符串中的所有html标记和特殊字符的方法。 使用完整报告,解析所有文本需要3分钟以上。 问题是我必须经常调用该方法

我发现org.apache.commons.lang.StringUtils是最快的,如果你不想打扰StringBuffer。

你可以像这样使用它:
noHTMLString = StringUtils.replace(noHTMLString, "

", "\n");

我做的性能测试比我自定义的StrinBuffer解决方案更糟糕,类似于@extraneon提出的解决方案。

它看起来像你在那里解析HTML,你有没有使用第三方库而不是重新发明轮子?

我同意Martijn使用现成的解决方案而不是自己解析它 – 在javax.xml包中有很多内置于Java中的东西。 一个简洁的解决方案是使用XSLT转换来替换,这看起来像是一个理想的用例。 但是,它很复杂。

要回答这个问题,您是否考虑过使用正则表达式库 ? 看起来你想要匹配许多不同的东西,并用相同的东西(\ n或空字符串)替换。 使用正则表达式,你可以使用像"
|
|
"
这样的表达式,或者像"更聪明地创建一个匹配器对象,你可以在其上调用replaceAll。

我完全同意Martijn的观点。 为工作选择合适的工具。

但是,如果您的文件不是HTML,但只包含一些HTML令牌,那么有几种方法可以加快速度。

首先,如果某些输入量不包含可替换元素,请考虑从以下内容开始:

 if (!input.contains('<')) { return input; } 

其次,考虑正则表达式:

 Pattern p = Pattern.compile( your_regex ); 

不要为每一个replaceAll行创建一个模式,而是尝试将它们组合在一起(正则表达式有一个OR运算符)并让Pattern优化正则表达式。 使用已编译的模式并且不在每次调用中编译它,它相当昂贵。

如果正则表达式有点复杂,您还可以自己实现一些更快(但可能不太可读)的替换引擎:

 StringBuilder result = new StringBuilder(input.length(); for (int i=0; i < input.length(); i++) { char c = input.charAt(i); if ( c != '<' ) { continue; } int closePos = input.indexOf( '>', i); if (closePos == -1) {// not found result.append( input.substring(i, input.length()); return result.toString(); } i = closePos; String token = input.substring(i, closePos); if ( token.equals( "p/" ) { result.append("\\n"); } else if (token.equals(...)) { } else if (...) { } } return result.toString(); 

这可能有一些错误:)

优点是您只需迭代输入一次。 最大的缺点是它并不容易理解。 您还可以编写一个状态机,分析每个字符应该是什么状态,这可能会更快,甚至更多的工作。