Bootstrap

java正则表达式效率

java正则表达式效率

  对于正则表达式的使用效率问题,我在网上看到的有两种截然不同的结果,到底它的效率如何,今天我用java来做了个则试。  解决的问题很简单,从一个字符串中把用正则表达式如href="[^\"]*"的字符串保存到一个list中去。先构造一个长字符串,再进行匹配操作。测试代码如下:

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

//传入的参数为构造的字符串长度
public void initContent(int count) {

//选用StringBuffer,可以选用String一试,体现双方拼接字符串的效率差异
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < count / 20; i++) {

     //为了简化,统一用一小段来循环
     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函数来实现
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));
    }

}

// 一个一个字符地去遍历判断

public void useOneToOneCode() {
    int length = content.length();
    for (int i = 0; i < length; i++) {

  //这里的实现有点依赖了目标的头字符了,为了简单忽略
     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;

     }

    }
}

//消耗时间记录,为了避免前后程序的干扰,在具体测试中,一个一个来测试记录时间
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) + "毫秒");
}

}

  测试过程中,每种方式单独运行,数据量为8000000字符,数据如下,纵坐标单位为毫秒,横坐标单位为次,如图1.1

图1.1

  当数据量小的时候如800字符到8个字符,使用正则表达式大约需25毫秒(猜想,所用时间消耗在正则式的解释中),而其它两种方式不足1毫秒,若数据量为80000字符,使用正则表达式大约需45毫秒,而其它两种方式大约为14毫秒。

  通过这次测试,正则表达式在开发coding中,阅读和防止出bug上有很大好处,但是其性能依然值得注意。

;