工作中经常会用到在文本中每行检索某种pattern,刚才测试了三种方式,发现实际性能和预想的有区别

方式1:

     直接字符串的matches方法,【string.matches("\\d+")】

方式2:

    先构建一个单行匹配的pattern,然后用这个pattern去match

    Pattern p1=Pattern.compile("\\d+");

    Matcher m=p1.matcher(sar[i]);

方式3:

    构建一个可以匹配换行符DOTALL模式的pattern,然后在整个文本中find

    Pattern p2=Pattern.compile("\\d+",Pattern.DOTALL );

    

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class TestRe {

    /**
     * @param args
     */
    public static void main(String[] args) {
        String s1="abc";
        String s2="123";
        //构建一个多行的字符串
        StringBuilder stb=new StringBuilder();
        for(int i=0;i<10000;i++){
            int k=new Random().nextInt()%2;
            if(k==0){
                stb.append(s1+"\n");
            }
            else{
                stb.append(s2+"\n");
            }
        }
        
        Pattern p2=Pattern.compile("\\d+",Pattern.DOTALL );
        Pattern p1=Pattern.compile("\\d+");
        String ts=stb.toString();
        String[] sar=ts.split("\n");
        test1(sar);
        test2(ts,p2);
        test3(sar,p1);
        
        
    
    }

    public static void test1(String[] sar){
        long st=System.nanoTime();
        List<String> l=new ArrayList<String>();
        for(int i=0;i<sar.length;i++){
            if(sar[i].matches("\\d+")){
                l.add(sar[i]);
            }
        }
        System.out.println("1Size"+l.size());
        long et=System.nanoTime();
        System.out.println("test1:"+(et-st)+"纳秒");
    }
    
    
    public static void test3(String[] sar,Pattern p1){
        long st=System.nanoTime();
        List<String> l=new ArrayList<String>();
        for(int i=0;i<sar.length;i++){
            Matcher m=p1.matcher(sar[i]);
            if(m.matches()){
                l.add(sar[i]);
            }
        }
        System.out.println("3Size"+l.size());
        long et=System.nanoTime();
        System.out.println("test3:"+(et-st)+"纳秒");
    }
    
    public static void test2(String s,Pattern p){
        long st=System.nanoTime();
        List<String> l=new ArrayList<String>();
        Matcher m=p.matcher(s);
        while(m.find()){
            l.add(m.group());
        }
        System.out.println("2Size"+l.size());
        long et=System.nanoTime();
        System.out.println("test2:"+(et-st)+"纳秒");
    }
    
}

面是运行结果,方法一竟然性能最低,在很简单的正则表达式或者不需要替换,不需要找出子匹配时,这个方法是我用的最多的,想不到性能最差。

测试一:

1Size4999
test1:53153038纳秒
2Size4999
test2:13393716纳秒
3Size4999
test3:4527045纳秒

测试二:

1Size4941
test1:38807545纳秒
2Size4941
test2:6826025纳秒
3Size4941
test3:3127127纳秒

看起来好像是方法三优于方法二,实则不然,如果把调用次序换下,方法二有会快于方法三,我的猜想是底层调用可能有单例对象什么的。先调用的pattern可能被复用。没做调查

调换后的结果:

测试一:

2Size5093
test2:12792156纳秒
3Size5093
test3:13665544纳秒
1Size5093
test1:56139648纳秒

测试二:

2Size4952
test2:12030397纳秒
3Size4952
test3:20046193纳秒
1Size4952
test1:40124475纳秒