簡體   English   中英

在Java中執行大量字符串替換的最快方法

[英]Fastest way to perform a lot of strings replace in Java

我必須編寫某種解析器來獲取String並用其他字符替換某些字符集。 代碼如下所示:

noHTMLString = noHTMLString.replaceAll("</p>", "\n");
noHTMLString = noHTMLString.replaceAll("<br/>", "\n\n");
noHTMLString = noHTMLString.replaceAll("<br />", "\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, "</p>", "\\n");

我做的性能測試比我自定義的StrinBuffer解決方案更糟糕,類似於@extraneon提出的解決方案。

它看起來像你在那里解析HTML,你有沒有使用第三方庫而不是重新發明輪子?

我同意Martijn使用現成的解決方案而不是自己解析它 - 在javax.xml包中有很多內置於Java中的東西。 一個簡潔的解決方案是使用XSLT轉換來替換,這看起來像是一個理想的用例。 但是,它很復雜。

要回答這個問題,您是否考慮過使用正則表達式庫 看起來你想要匹配許多不同的東西,並用相同的東西(\\ n或空字符串)替換。 使用正則表達式,您可以使用像"<br>|<br/>|<br />"這樣的表達式,或者更像<br.*?>"這樣的表達式來創建匹配器對象,您可以在其上調用replaceAll。

我完全同意Martijn的觀點。 為工作選擇合適的工具。

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

首先,如果某些數量的輸入不包含可替換元素,請考慮從以下內容開始:

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

其次,考慮正則表達式:

Pattern p = Pattern.compile( your_regex );

不要為每一個replaceAll行創建一個模式,而是嘗試將它們組合在一起(regex有一個OR運算符)並讓Pattern優化正則表達式。 使用已編譯的模式並且不在每次調用中編譯它,它相當昂貴。

如果regex有點復雜,你也可以自己實現一些更快(但可能不太可讀)的替換引擎:

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

這可能有一些錯誤:)

優點是您只需要遍歷輸入一次。 最大的缺點是它並不容易理解。 你也可以編寫一個狀態機,分析每個字符應該是什么狀態,這可能會更快,甚至更多的工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM