2013-03-08 31 views
-1

我有一個字符串(關鍵字)數組,我需要檢查一個較大字符串(從文件中讀取的文本)中存在多少個字符串。我需要檢查是不區分大小寫的。 這時我做什麼是這樣的:查找子串的最高性能

private void findKeywords() { 
     String body = email.getMessage(); 
     for (String word : keywords) { 
      if (body.toLowerCase().contains(word.toLowerCase())) { 
       //some actions    } 
      if (email.getSubject().contains(word)) { 
       //some actions 
      } 
     } 
    } 

從閱讀中的問題在這裏另一種解決方案提出了:

private void findKeywords() { 
     String body = email.getMessage(); 
     for (String word : keywords) { 
      boolean body_match = Pattern.compile(Pattern.quote(word), Pattern.CASE_INSENSITIVE).matcher(body).find(); 
      boolean subject_match = Pattern.compile(Pattern.quote(word), Pattern.CASE_INSENSITIVE).matcher(email.getSubject()).find(); 
      if (body_match) { 
       rating++; 
      } 
      if (subject_match) { 
       rating++; 
      } 
     } 
    } 

哪個這些解決方案的效率更高?還有另一種方法可以做到這一點更好嗎?任何可接受的解決方案都必須易於實施(與上述相同),最好不使用外部庫,因爲在這種情況下這不是非常重要的問題。

+2

爲什麼不嘗試每一個,看看哪一個運行最快的??? – 2013-03-08 21:03:15

+0

因爲那麼我不知道是否有更快的解決方案從上面。 – Giannis 2013-03-08 21:06:31

+1

http://codereview.stackexchange.com – 2013-03-08 21:07:47

回答

2

這兩種解決方案對我來說似乎都是可行的。我建議的一個改進是將函數移出循環。在您當前的代碼中,您將重複執行諸如toLowerCase()和Pattern.compile之類的操作,您只需執行一次即可。

顯然有更快的方法來解決這個問題,但他們需要比這些五行更復雜的代碼。

+0

將「toLowerCase()」移到循環外部不僅具有性能優勢,還可減少一些可能的巨大字符串重複。 – 2013-03-08 21:13:57

0

我認爲你提到的顯式regex解決方案會更有效率,因爲它沒有toLowerCase操作,它會將輸入字符串複製到內存中並使字符變爲小寫。

這兩種解決方案應該是實用的,你的問題主要是學術問題,但我認爲正則表達式提供了更清晰的代碼。

+0

我覺得你對'String.contains()'使用正則表達式下面是錯誤的。你在說哪個JDK? – 2013-03-08 21:12:58

+0

我正在考慮replaceAll – Javanator 2013-03-08 21:16:51

1

更好:構建一個包含所有關鍵字的單一模式。然後搜索該模式。假設您的關鍵字不包含元字符(在模式特殊含義的字符),然後使用:

StringBuilder keywordRegex = new StringBuilder(); 
for (String w : keywords) { 
    keywordRegex.append("|"+w); 
} 
Pattern p = Pattern.compile(keywordRegex.substring(1)); 
Matcher m = new p.matcher(textToMatch); 
while (m.find()) { 
    // match is at m.start(); word is m.group(0); 
} 

不是通過所有關鍵字迭代更加高效:模式編譯(一次)將已生成尋找一個自動機所有關鍵字一次。

+0

爲了增強健壯性,您需要轉義每個關鍵字,但隨着關鍵詞越多,這種關係越好。 – 2013-03-08 21:36:47

0

如果您的電子郵件的身體是非常大的,寫一個專門的不區分大小寫包含可能是合理的,因爲你可以避開大的字符串調用toUpperCase():

static bool containsIgnoreCase(String big, String small) { 
    if (small == null || big == null || small.length() > big.length()) { 
    return false; 
    }  
    String smallLC = small.toLowerCase(); 
    String smallUC = small.toUpperCase(); 
    for (int i = 0; i < big.length(); ++i) { 
    if (matchesAt(big, i, smallLC, smallUC)) { 
     return true; 
    } 
    } 
    return false; 
} 

private static bool matchesAt(String big, int index, String lc, String uc) { 
    if (index + lc.length() > big.length()) { 
    return false; 
    } 
    for (int i = 0; i < lc.length(); ++i) { 
    char c = big.charAt(i + index); 
    if ((c != lc.charAt(i)) && (c != uc.charAt(i))) { 
     return false; 
    } 
    } 
    return true; 
}