java中字符串的精确匹配_Java最佳实践–字符串性能和精确字符串匹配
java中字符串的精確匹配
在使用Java編程語言時(shí),我們將繼續(xù)討論與建議的實(shí)踐有關(guān)的系列文章,我們將討論String性能調(diào)優(yōu)。 我們將專注于如何有效地處理字符串創(chuàng)建, 字符串更改和字符串匹配操作。 此外,我們將提供我們自己的用于精確字符串匹配的最常用算法的實(shí)現(xiàn)。 與Java開發(fā)工具包中提供的用于精確字符串匹配的幼稚方法相比,這些算法中的許多算法都可以實(shí)現(xiàn)更好的性能。 本文以上述精確字符串匹配算法之間的性能比較作為結(jié)束。所有討論的主題均基于用例,這些用例源于電信行業(yè)關(guān)鍵任務(wù)超高性能生產(chǎn)系統(tǒng)的開發(fā)。
在閱讀本文的每個(gè)部分之前,強(qiáng)烈建議您參考相關(guān)的Java API文檔以獲取詳細(xì)信息和代碼示例。
所有測試均針對具有以下特征的Sony Vaio進(jìn)行:
- 系統(tǒng):openSUSE 11.1(x86_64)
- 處理器(CPU):Intel(R)Core(TM)2 Duo CPU T6670 @ 2.20GHz
- 處理器速度:1,200.00 MHz
- 總內(nèi)存(RAM):2.8 GB
- Java:OpenJDK 1.6.0_0 64位
應(yīng)用以下測試配置:
- 并發(fā)工作者線程數(shù):1
- 每個(gè)工作人員重復(fù)測試的線程數(shù):1000
- 整體測試次數(shù):100
字符串性能調(diào)優(yōu)
許多人在使用String對象時(shí)并沒有考慮性能。 但是,濫用String類可能會嚴(yán)重降低應(yīng)用程序的性能。 您應(yīng)該記住的最重要的事情是:
“最初為空的字符串池由String類私下維護(hù)。
調(diào)用intern方法時(shí),如果池已經(jīng)包含等于equals(Object)方法確定的此String對象的字符串,則返回池中的字符串。
否則,將此String對象添加到池中,并返回對此String對象的引用。
因此,對于任何兩個(gè)字符串s和t,當(dāng)且僅當(dāng)s.equals(t)為true時(shí),s.intern()== t.intern()才為true。
所有文字字符串和字符串值常量表達(dá)式都將被嵌入。”
我們在處理String類時(shí)建議的最佳做法如下:
模式優(yōu)先精確字符串匹配
Java語言缺少快速的字符串搜索算法。 字符串 “ indexOf(...)”和“ lastIndexOf(...)”操作針對源文本對所提供的模式進(jìn)行幼稚搜索。 天真的搜索基于“強(qiáng)力”模式第一個(gè)精確的字符串匹配算法。 “蠻力”算法包括檢查文本中所有位置的模式是否從那里開始。 然后,在每次嘗試后,它都會將圖案向右精確地移動一個(gè)位置。 但是,仍然存在其他幾種算法,它們在速度和效率上都遠(yuǎn)勝過“蠻力”算法。
應(yīng)用程序需要兩種解決方案,具體取決于首先給出哪個(gè)字符串,模式或文本。 在我們的例子中,模式是預(yù)先提供的,這意味著我們總是針對未知文本搜索提供的模式。 對于需要全文搜索(文本優(yōu)先精確字符串匹配)的所有應(yīng)用程序,需要一套不同的算法來提供索引掃描。 Apache Lucene是實(shí)現(xiàn)后一種算法家族的最受歡迎的文本搜索引擎庫之一。 盡管如此,本文僅研究第一類算法。
感謝這項(xiàng)偉大的工作,來自魯昂大學(xué)信息學(xué)院的魯昂大學(xué)的Christian Charras和Thierry Lecroq的一本書名為“ 精確字符串匹配算法 ”,我們得以用Java實(shí)現(xiàn)最精確的字符串匹配算法。 ,先給出模式。 下面的列表顯示Christian Charras和Thierry Lecroq所提供的算法名稱,并在括號中顯示我們的算法實(shí)現(xiàn)“代碼名稱”。 有關(guān)每種算法的更多信息,請單擊相應(yīng)的鏈接,以便重定向到“精確字符串匹配算法”這本書的相關(guān)部分。
- 蠻力算法 (BF)
- 確定性有限自動機(jī)算法 (DFA)
- Karp-Rabin算法 (KR)
- 移位或算法 (SO)
- Morris-Pratt算法 (MP)
- Knuth-Morris-Pratt算法 (KMP)
- 西蒙算法 (SMN)
- Colussi算法 (CLS)
- Galil-Giancarlo算法 (GG)
- Apostolico-Crochemore算法 (AC)
- 不太天真算法 (NSN)
- Boyer-Moore算法 (BM)
- Turbo BM算法 (TBM)
- Apostolico-Giancarlo算法 (AG)
- 反向Colussi算法 (RC)
- Horspool算法 (HP)
- 快速搜索算法 (QS)
- 調(diào)優(yōu)的Boyer-Moore算法 (BMT)
- Zhu-Takaoka算法 (ZT)
- Berry-Ravindran算法 (BR)
- 史密斯算法 (SMT)
- Raita算法 (RT)
- 逆因子算法 (RF)
- Turbo逆因子算法 (TRF)
- 前向Dawg匹配算法 (FDM)
- 后向不確定Dawg匹配算法 (BNDM)
- 向后Oracle匹配算法 (BOM)
- Galil-Seiferas算法 (GS)
- 雙向算法 (TW)
- 有序字母字符串匹配算法 (SMOA)
- 最佳失配算法 (OM)
- 最大移位算法 (MS)
- 跳過搜索算法 (SS)
- KMP跳過搜索算法 (KPMSS)
在“精確字符串搜索算法”套件的初始版本(1.0.0)中,對于每種算法,我們都實(shí)現(xiàn)了三個(gè)實(shí)用程序操作:
- compile(String pattern)–基于提供的模式執(zhí)行所有必要預(yù)處理的靜態(tài)操作
- findAll(String source)–返回包含所有索引的列表,其中搜索算法指示有效的模式匹配
- findAll(String pattern,String source)–這是一個(gè)輔助靜態(tài)操作,封裝了上述兩個(gè)操作的功能
以下是使用Boyer-Moore算法(BM)的示例:
情況1
BM bm = BM.compile(pattern); List<Integer> idx = bm.findAll(source); List<Integer> idx2 = bm.findAll(source2); List<Integer> idx3 = bm.findAll(source3);情況#2
List<Integer> idx = BM.findAll(pattern, source);在第一種情況下,我們編譯模式并以兩個(gè)不同的步驟執(zhí)行搜索。 當(dāng)我們必須在多個(gè)源文本中搜索同一模式時(shí),此方法是合適的。 通過編譯模式,由于預(yù)處理通常是繁重的操作,因此我們可以最大化性能結(jié)果。 另一方面,對于一次搜索,第二種方法提供了更方便的API。
我們必須指出我們提供的實(shí)現(xiàn)是線程安全的,并且當(dāng)前我們不支持模式中的正則表達(dá)式。
以下是我們的精確字符串搜索算法套件的算法實(shí)現(xiàn)之間的示例性能比較。 我們使用65535個(gè)字符的完整字母大小,在1150000個(gè)字符的文本中搜索了一個(gè)故意不存在的37個(gè)字符的短語。 請不要忘記這是一個(gè)相對的性能比較。 絕大多數(shù)提供的搜索算法的性能結(jié)果在很大程度上取決于提供的文本,提供的模式和字母大小。 因此,您應(yīng)該只將String搜索算法之間的所有性能比較視為相對的。
在本節(jié)的開頭,我們已經(jīng)聲明Java語言缺少快速的String搜索算法。 但是,與我們的算法套件相比,標(biāo)準(zhǔn)的Java天真的實(shí)現(xiàn)有多慢? 為了回答上述問題,我們實(shí)現(xiàn)了兩種方法,以便使用標(biāo)準(zhǔn)Java API檢索潛在模式匹配的所有索引值:
方法1 – indexOf()方法
public static List<Integer> findAll(String pattern, String source) { List<Integer> idx = new ArrayList<Integer>(); int id = - 1 ; int shift = pattern.length(); int scnIdx = -shift; while (scnIdx != - 1 || id == - 1 ) { idx.add(scnIdx); id = scnIdx + shift; scnIdx = source.indexOf(pattern, id); } idx.remove( 0 ); return idx; }方法2 – Matcher find()方法
public static List<Integer> findAll(String pattern, String source) { List<Integer> idx = new ArrayList<Integer>(); Pattern ptrn = Pattern.compile(pattern); Matcher mtch = ptrn.matcher(source); while (mtch.find()) idx.add(mtch.start()); ??return idx; }下面我們給出上述搜索算法之間的性能比較表
水平軸表示每種算法進(jìn)行預(yù)處理和解析提供的文本所需的平均時(shí)間(以毫秒為單位)。 因此,較低的值更好。 如您所見,Java天真實(shí)現(xiàn)(indexOf()方法)以及幾乎所有搜索算法實(shí)現(xiàn)都優(yōu)于Java Matcher“ find()”方法。 換句話說,當(dāng)您處理中小型字符串搜索時(shí),最好使用上面提供的代碼片段之類的東西,而不要使用更復(fù)雜的字符串搜索算法。 另一方面,處理大型文檔時(shí),我們套件中最快的算法之一肯定會派上用場!
您可以在此處下載精確字符串搜索算法套件發(fā)行版的1.0.0版
快樂編碼
賈斯汀
相關(guān)文章 :- Java最佳實(shí)踐–多線程環(huán)境中的DateFormat
- Java最佳實(shí)踐–高性能序列化
- Java最佳實(shí)踐– Vector vs ArrayList vs HashSet
- Java最佳實(shí)踐–隊(duì)列之戰(zhàn)和鏈接的ConcurrentHashMap
- Java最佳實(shí)踐– Char到Byte和Byte到Char的轉(zhuǎn)換
- 將String轉(zhuǎn)換為字節(jié)數(shù)組UTF編碼
- 將字符串轉(zhuǎn)換為字節(jié)數(shù)組ASCII編碼
- 使用indexOf方法搜索字符串
- StringBuffer追加方法
- StringTokenizer計(jì)數(shù)令牌
- 使用StringTokenizer反轉(zhuǎn)字符串
翻譯自: https://www.javacodegeeks.com/2010/09/string-performance-exact-string.html
java中字符串的精確匹配
總結(jié)
以上是生活随笔為你收集整理的java中字符串的精确匹配_Java最佳实践–字符串性能和精确字符串匹配的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 好看的系统流小说排行榜(四本顶级系统流小
- 下一篇: swing 选择对话框_Java Swi