关于正则表达式的性能

/**
     * @param temp 尊敬的${name},您正在进行${action}操作
     * @param msg  尊敬的张三,您正在进行找回密码操作
     * @return
     */
    private static Map<String, String> getParamMap(String temp, String msg) {
        // 尊敬的\$\{(.*?)},您正在进行\$\{(.*?)}操作
        String template1 = temp.replaceAll("\\$\\{(.*?)}", "\\\\\\$\\\\{(.*?)}");
        // 尊敬的(.*?),您正在进行(.*?)操作
        String template2 = temp.replaceAll("\\$\\{(.*?)}", "(.*?)");

        // [name, action]
        List<String> list1 = new ArrayList<>();
        // [张三, 找回密码]
        List<String> list2 = new ArrayList<>();
        Map<String, String> map = new HashMap<>();

        Pattern p1 = Pattern.compile(template1);
        Matcher m1 = p1.matcher(temp);

        if (m1.find()) {
            for (int i = 1; i <= m1.groupCount(); i++) {
                list1.add(m1.group(i));
            }
        }

        Pattern p2 = Pattern.compile(template2);
        Matcher m2 = p2.matcher(msg);
        if (m2.find()) {
            for (int i = 1; i <= m2.groupCount(); i++) {
                list2.add(m2.group(i));
            }
        }
        for (int i = 0; i < list1.size(); i++) {
            map.put(list1.get(i), list2.get(i));
        }
        return map;
    }

    @Deprecated
    private static Map<String, String> getParamMapOld(String template, String msg) {
        if (template == null || msg == null) {
            return null;
        }
        StringBuilder sbTem = new StringBuilder(template);
        StringBuilder sb = new StringBuilder(msg);
        Map<String, String> map = new HashMap<>();
        boolean isFirst = true;
        while (true) {
            int startT = sbTem.indexOf("${");
            if (startT == -1) {
                break;
            }
            if(isFirst){
                isFirst = false;
                if(startT>0){
                    String beforeT = template.substring(0,startT);
                    if(msg.indexOf(beforeT)!=0){
                        throw new RuntimeException("信息与模板格式不匹配!");
                    }
                }
            }
            int endT = sbTem.indexOf("}");
            if(endT==-1){
                break;
            }
            String afterT = sbTem.substring(endT + 1);
            int next = afterT.indexOf("${");
            int end;
            if (next == -1 || afterT.length() < 1) {
                //如果之后没有$了则取到最后
                end = sb.length()-(sbTem.length() - endT-1);
            } else {
                String after = afterT.substring(0, next);
                end = sb.indexOf(after);
                if (end == -1) {
                    throw new MessageCenterException("信息与模板格式不匹配!");
                }
            }
            //截取${}中的字段
            String subT = sbTem.substring(startT + 2, endT);
            String sub = sb.substring(startT, end);
            map.put(subT, sub);
            sbTem = new StringBuilder(sbTem.substring(endT + 1));
            sb = new StringBuilder(sb.substring(end));
        }
        return map;
    }

    public static void main(String[] args) {
        String template = "${test}尊敬的${name},您正在进行${asdf}操作,验证码:${code},请在${time}之内操作${32323}分";
        String msg = "TEST尊敬的张三,您正在进行找回密码操作,验证码:asdf,请在5分钟之内操作9995998分";

        log.info("startTime"+new Date());
        Map<String, String> map = new HashMap<>();
        for(int i=0;i<99999999;i++){
            map= getParamMap(template, msg);
        }
        for (String key : map.keySet()) {
            System.out.println(key + " : " + map.get(key));
        }
        log.info("endTime"+new Date());
        log.info("***********");
        log.info("startTime"+new Date());
        Map<String, String> mapOld = new HashMap<>();
        for(int i=0;i<99999999;i++){
            mapOld= getParamMapOld(template, msg);
        }
        for (String key : mapOld.keySet()) {
            System.out.println(key + " : " + mapOld.get(key));
        }
        log.info("endTime"+new Date());
    }

如上,是从短信中取出系统添加的参数。
分别采用了正则,和手动撸两种方式。

16:58:31.901 [main] INFO com.yunzainfo.cloud.message.center.phone.DayuPhoneUtil - startTimeThu Sep 19 16:58:31 CST 2019
code : asdf
32323 : 9995998
test : TEST
name : 张三
asdf : 找回密码
time : 5分钟
16:59:31.102 [main] INFO com.yunzainfo.cloud.message.center.phone.DayuPhoneUtil - endTimeThu Sep 19 16:59:31 CST 2019
16:59:31.102 [main] INFO com.yunzainfo.cloud.message.center.phone.DayuPhoneUtil - ***********
16:59:31.102 [main] INFO com.yunzainfo.cloud.message.center.phone.DayuPhoneUtil - startTimeThu Sep 19 16:59:31 CST 2019
code : asdf
32323 : 9995998
test : TEST
name : 张三
asdf : 找回密码
time : 5分钟
16:59:42.305 [main] INFO com.yunzainfo.cloud.message.center.phone.DayuPhoneUtil - endTimeThu Sep 19 16:59:42 CST 2019

可以看到正则用了整整一分钟,手动撸只用了11秒。(而且笔者函数只是随手写的没有优化)

所以如果对性能有要求,还是要手撸。

不过正则写起来是真的简单,真香。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值