對于正則表達式的使用效率問(wèn)題,我在網(wǎng)上看到的有兩種截然不同的結果,到底它的效率如何,今天我用java來(lái)做了個(gè)則試。
解決的問(wèn)題很簡(jiǎn)單,從一個(gè)字符串中把用正則表達式如href="[^\"]*"的字符串保存到一個(gè)list中去。先構造一個(gè)長(cháng)字符串,再進(jìn)行匹配操作。
測試代碼如下:
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Reg {
public String content = "";
public List userRegList = new LinkedList();
public List userCommonList = new LinkedList();
public List userOneToOneList = new LinkedList();
//傳入的參數為構造的字符串長(cháng)度
public void initContent(int count) {
//選用StringBuffer,可以選用String一試,體現雙方拼接字符串的效率差異
StringBuffer sb = new StringBuffer();
for (int i = 0; i < count / 20; i++) {
//為了簡(jiǎn)化,統一用一小段來(lái)循環(huán)
sb.append("abc href=\"abcd\"abce");
}
this.content = sb.toString();
}
//使用正則表達式方式
public void useRegCode() {
Pattern p = Pattern.compile("href=\"[^\"]*\"", Pattern.CANON_EQ);
Matcher match = p.matcher(this.content);
while (match.find()) {
userRegList.add(match.group(0));
}
}
// 主要使用字符串中提供的find函數來(lái)實(shí)現
public void useCommonCode() {
int i = 0;
int index = 0;
while ((index = content.indexOf("href=\"", i)) != -1) {
int endIndex = content.indexOf("\"", index + 6);
i = endIndex + 1;
userCommonList.add(content.substring(index, endIndex + 1));
}
}
// 一個(gè)一個(gè)字符地去遍歷判斷
public void useOneToOneCode() {
int length = content.length();
for (int i = 0; i < length; i++) {
//這里的實(shí)現有點(diǎn)依賴(lài)了目標的頭字符了,為了簡(jiǎn)單忽略
if (content.charAt(i) == 'h' && i + 5 < length
&& content.substring(i, i + 5).equals("href=")) {
int j = i + 6;
boolean match = false;
for (; j < length; j++) {
if (content.charAt(j) == '\"') {
match = true;
break;
}
}
j++;
if (match) {
userOneToOneList.add(content.substring(i, j));
}
i = j;
}
}
}
//消耗時(shí)間記錄,為了避免前后程序的干擾,在具體測試中,一個(gè)一個(gè)來(lái)測試記錄時(shí)間
public static void main(String[] args) {
Reg r = new Reg();
r.initContent(8000000);
// 使用OneToOne
long t5 = System.currentTimeMillis();
r.useOneToOneCode();
long t6 = System.currentTimeMillis();
System.out.println("你的程序運行了:" + (int) ((t6 - t5) / 1000) + "秒"
+ ((t6 - t5) % 1000) + "毫秒");
// 使用正則表達式
long t3 = System.currentTimeMillis();
r.useRegCode();
long t4 = System.currentTimeMillis();
System.out.println("你的程序運行了:" + (int) ((t4 - t3) / 1000) + "秒"
+ ((t4 - t3) % 1000) + "毫秒");
// 使用find
long t1 = System.currentTimeMillis();
r.useCommonCode();
long t2 = System.currentTimeMillis();
System.out.println("你的程序運行了:" + (int) ((t2 - t1) / 1000) + "秒"
+ ((t2 - t1) % 1000) + "毫秒");
}
}
測試過(guò)程中,每種方式單獨運行,數據量為8000000字符,數據如下,縱坐標單位為毫秒,橫坐標單位為次,如圖1.1
圖1.1
當數據量小的時(shí)候如800字符到8個(gè)字符,使用正則表達式大約需25毫秒(猜想,所用時(shí)間消耗在正則式的解釋中),而其它兩種方式不足1毫秒,若數據量為80000字符,使用正則表達式大約需45毫秒,而其它兩種方式大約為14毫秒。
通過(guò)這次測試,正則表達式在開(kāi)發(fā)coding中,閱讀和防止出bug上有很大好處,但是其性能依然值得注意。