原文链接:https://www.baeldung.com/java-regex-performance

作者: baeldung

译者:Darren Luo

1. 概述

在本快速教程中,我们将展示模式匹配引擎是如何工作的。我们还将介绍在 Java 中优化正则表达式的不同方式。

有关正则表达式的的使用介绍,请参阅此文

2. 模式匹配引擎

java.util.regex 包使用了一种叫做 Nondeterministic Finite Automaton(NFA)(不确定性有穷自动机)的模式匹配引擎。它被认为是不确定的是因为在对给定字符串尝试匹配正则表达式时,输入的每个字符可能针对正则表达式的不同部分进行多次检查。

在后台,上面提到的引擎使用回溯。这种通用算法尝试用尽所有可能性,知道它宣告失败。考虑下面的示例可以更好的理解 NFA:

"tra(vel|ce|de)m"

在输入字符串“travel”时,该引擎首先会查找“tra”并立即找到它。

在这之后,它将从第四个字符开始尝试匹配“vel”。这将匹配上,所以她将继续并尝试匹配”m“。

那将不能匹配,因此,它将回到第四个字符并搜索”ce“。这次将不再匹配,所以它将再次回到第四个位置并尝试匹配”de“。这个字符串耶不能匹配,因此它将返回输入字符串的第二个字符并尝试搜索另一个“tra”。

最后一次失败时,算法将返回失败。

在上面的简单例子里,在尝试将输入字符串和正则表达式匹配时,引擎必须多次回溯。因此,减少回溯次数时非常重要的。

3. 优化正则表达式的方法

3.1 避免重新编译

Java 中的正则表达式被编译为内部数据接口。这个编译时一个耗时的过程。

我们每次调用 String.matches(String regex) 方法时,制定的正则表达式都会重新编译。

if (input.matches(regexPattern)) {
// do something
}

我们可以看到,每次进行条件求值时,正则表达式将被编译。

要进行优化,只能首先编译模式,然后创建一个 Matcher 来查找值中的匹配:

Pattern pattern = Pattern.compile(regexPattern);
for(String value : values) {
Matcher matcher = pattern.matcher(value);
if (matcher.matches()) {
// do something
}
}

上述优化的替代方案时使用相同的 Matcher 示例及其 reset() 方法:

Pattern pattern = Pattern.compile(regexPattern);
Matcher matcher = pattern.matcher("");
for(String value : values) {
matcher.reset(value);
if (matcher.matches()) {
// do something
}
}

由于 Matcher 不是线程安全的情况,我们必须谨慎使用这种变体。在多线程场景中可能存在危险。

总而言之,无论哪种情况,我们都保证在任何时间点都只有一个 Matcher 用例,可以用 reset 来重用它。对于这个例子,重复使用预编译已经足够了。

3.2. 使用替换(Alternation)

正如上一节我们测试的那样,替换使用不当可能会对性能产生影响。最重要的是将选项放置最可能发生的前方,这样能更快的匹配。

此外,我们必须提取提取他们之间的共同模式。下面两个是不一样的:

(travel | trade | trace)

对比:

tra(vel | de | ce)

后一个更快,因为 NFA 将尝试匹配“tra”,如果没找到它,则不会尝试任何替代方案。

3.3. 捕获分组(Group)

每次我们捕获分组时,我们都会遭受一次小规模的惩罚。

如果我们需要在分组里捕获文本,我们应该考虑使用非捕获分组。请用“(?:M)”替代使用“(M)”。

总结

在这篇短文中,我们简要回顾了 NFA 的工作原理。然后,我们通过与扁我们的模式并重用 Matcher 来探索如何优化我们正则表达式的性能。

最后,我们指出我们在使用替换和分组的一些注意事项。

和往常一样,可以在 Github 上找到完整的源代码。

http://www.spring4all.com/article/1479

译:Java 中的正则表达式性能概述的更多相关文章

  1. 9.JAVA中的正则表达式

    一.JAVA中的正则表达式 1.概念:以某种特定的方式描述字符串 1.Java中正则表达式的规则 ?          #{0,1}-?有一个-或者没有 \\           #表示一个" ...

  2. JAVA中的正则表达式--待续

    1.关于“\”,在JAVA中的正则表达式中的不同: 在其他语言中"\\"表示为:我想要在正则表达式中插入一个普通的反斜杠: 在Java中“\\”表示为:我想要插入一个正则表达式反斜 ...

  3. java中使用正则表达式匹配字符串

    在Java中使用正则表达式去匹配相应的字符串: String importFileRole = "(import)\\s*[a-zA-Z0-9_<>.]+\\;";// ...

  4. (转)Java中使用正则表达式的一个简单例子及常用正则分享

    转自:http://www.jb51.net/article/67724.htm 这篇文章主要介绍了Java中使用正则表达式的一个简单例子及常用正则分享,本文用一个验证Email的例子讲解JAVA中如 ...

  5. 【java 正则表达式】记录所有在java中使用正则表达式的情况

    本篇记录在java中邂逅正则表达式的所有美丽瞬间.因为在java和js中正则表达式的语法并不一致. 1.匹配字符串中有出现[2.1开头或者&2.1或者&3.1等的] Pattern m ...

  6. Java中String连接性能的分析【转】

    [转]http://www.blogjava.net/javagrass/archive/2010/01/24/310650.html 总结:如果String的数量小于4(不含4),使用String. ...

  7. java 中使用正则表达式操作字符串

    import java.awt.Toolkit; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.DataFl ...

  8. java中的正则表达式捕获组与引用的概念

    今天群里有个人问,怎样用增则表达式匹配三角形的三边,其实只是要匹配三个数字而已,如 301 402 503 开始认为很简单,我就写了一个   "(([1-9]\\d?)\\s){2}$2&q ...

  9. Java中String连接性能的分析

    总结:如果String的数量小于4(不含4),使用String.concat()来连接String,否则首先计算最终结果的长度,再用该长度来创建一个StringBuilder,最后使用这个String ...

随机推荐

  1. 生成0-42之间的7个不重复的int值

    public static void main(String[] args) { //set集合存储不重复无序的值 Set<Integer> set = new HashSet<In ...

  2. BZOJ_1818_[Cqoi2010]内部白点 _扫描线+树状数组

    BZOJ_1818_[Cqoi2010]内部白点 _扫描线+树状数组 Description 无限大正方形网格里有n个黑色的顶点,所有其他顶点都是白色的(网格的顶点即坐标为整数的点,又称整点).每秒钟 ...

  3. ACM学习历程—ZOJ 3861 Valid Pattern Lock(dfs)

    Description Pattern lock security is generally used in Android handsets instead of a password. The p ...

  4. javaCV入门指南:序章

    前言 从2016年6月开始写<javacv开发详解>系列,到而今的<javacv入门指南>,虽然仅隔了两年多时间,却也改变了很多东西. 比如我们的流媒体技术群从刚开始的两三个人 ...

  5. win 10 无线标志都不出现

    http://jingyan.baidu.com/article/e75057f2fdd2f1ebc91a89f1.html ipconfig /flushdns netsh winsock rese ...

  6. 2014 ACM广东省赛总结

    2014年广东省赛在化工大学城开,5月10日开幕式&热身赛,5月11日正式赛. 热身赛的时候,开幕式说有两小时,于是我们愉快的切题了,像平常组队赛那样很快出了两题,但卡在后面两题切不动了.这时 ...

  7. adt eclipse 配置问题 error:could not open ...jvm.cfg

    在安装adt eclipse后,打开eclipse提示error:could not open eclipse\jre\lib\amd64\jvm.cfg 据网上显示原因应该是以前安装过java,然后 ...

  8. Bind 远程连接DNS服务器时出现 rndc: connection to remote host closed

    使用命令:rndc -s 192.168.1.2 status 连接远程的bind 搭建的DNS服务器时出现下面的错误:   rndc: connection to remote host close ...

  9. 网站特效离不开脚本,javascript是最常用的脚本语言,我们归纳一下常用的基础函数和语法:

    转载自网络,非原创 1.输出语句:document.write(""); 2.JS中的注释为//3.传统的HTML文档顺序是:document->html->(head ...

  10. SmartSql使用教程(2)——使用动态代理实现CURD

    一.引言 接着上一篇的教程,本章我们继续讲SmartSql.今天的主题是动态仓储. 老规矩,先上一个项目结构 从第二章开始.我们将原来的单一项目做了一个分离.方便之后的更新. 在这个结构中.原本上一章 ...