译者: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正则表达式性能_译:Java 中的正则表达式性能概述相关推荐

  1. java matcher函数_在Java正则表达式中使用Matcher.end()方法

    方法java.util.regex.Matcher.end()返回根据正则表达式从序列中匹配最后一个字符后的偏移值.此方法不需要任何参数.如果没有匹配发生,或者匹配操作失败,则抛出IllegalSta ...

  2. java正则表达式 匹配()_学习Java正则表达式(匹配、替换、查找)

    import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; public c ...

  3. java skip函数_【Java必修课】图说Stream中的skip()和limit()方法及组合使用

    1 简介 本文将讲解Java 8 Stream中的两个方法:skip()和limit().这两个方法是Stream很常用的,不仅各自会被高频使用,还可以组合出现,并能实现一些小功能,如subList和 ...

  4. bigint对应java什么类型_「JAVA」从格式化输出到扫描输入,深究Java正则表达式匹配之道

    字符串是不可变的 字符串是不可变的,也就是说当字符串的内容发生改变的时候,会创建一个新的String对象:但是如果内容没有发生改变的时候,String类的方法会返回原字符串对象的引用. 而正则表达式往 ...

  5. java coin介绍_代码示例中的Java 7:Project Coin

    java coin介绍 该博客通过代码示例介绍了一些新的Java 7功能,这些项目在Project Coin一词下进行了概述. Project Coin的目标是向JDK 7添加一组小的语言更改.这些更 ...

  6. java正则表达式面试_【Java面试宝典】正则表达式

    ● 请你谈谈Java中是如何支持正则表达式操作的? 考察点:正则表达式 参考回答: Java中的String类提供了支持正则表达式操作的方法,包括:matches().replaceAll().rep ...

  7. java实现分而治之_并发编程中一种经典的分而治之的思想!!

    写在前面 在JDK中,提供了这样一种功能:它能够将复杂的逻辑拆分成一个个简单的逻辑来并行执行,待每个并行执行的逻辑执行完成后,再将各个结果进行汇总,得出最终的结果数据.有点像Hadoop中的MapRe ...

  8. java final 类_在Java中,final修饰的类有什么特点

    展开全部 关于Java中的32313133353236313431303231363533e4b893e5b19e31333264663736final(2010-09-09 14:19:48)转载▼ ...

  9. java logging包_用JDK中提供的java.util.logging.*包创建Logger对象----原创

    由于项目中用到了Applet与Servlet之间(客户端用Applet.Server端用Servlet)的通信,要求: 1:>客户端与服务端必须出Log. 2:>浏览器在加载Applet时 ...

最新文章

  1. python close函数_Matplotlib的close()函数使Tkinter GUI窗口关闭
  2. 数据库的小知识——主从架构
  3. mingw w64 v8.0.0_使用Visual Studio Code和MinGW编译运行C++代码
  4. Cosmos OpenSSD--greedy_ftl1.2.0(一)
  5. 【问题1】为什么连接的时候是三次握手,关闭的时候却是四次握手?
  6. 返回值是内置类型 不能更改_选择通过更改内容类型返回的详细程度,第二部分...
  7. 论文浅尝 | 用于嵌套命名实体识别的二部平面图网络(BiFlaG)
  8. 分享一篇竞品分析报告
  9. 2017.3.30 时态同步 失败总结
  10. poj3254(状压dp入门第一道题,很详细)
  11. QT学习之自定义控件
  12. jdk7对list进行排序(按照list中entity的某个属性比如age)
  13. PS抠图小技巧-【色彩范围】
  14. 苹果开发者账号续费相关问题
  15. linux定时任务(crontab)
  16. Java file.encoding
  17. 文件无法删除 你需要计算机管理员 提供的权限才能对此文件进行更改解决办法
  18. 第39级台阶 小明刚刚看完电影《第39级台阶》,离开电影院的时候,他数了数礼堂前的台阶数,恰好是39级!
  19. 经典书籍《征服市场的人》阅读心得
  20. Murmur Hash 例子

热门文章

  1. OSGI –模块化您的应用程序
  2. xp系统的计算机管理中用户在哪里,WINDOWSXP的用户管理和系统安全设置
  3. 安全审计报告_企业做税审的五大好处!税审报告和审计报告的区别
  4. macOS下如何使用命令启动数据库/停止数据库/重启数据库(MySQL)
  5. 如何理解Java的类变量、成员变量、常量、类属性、实例属性、字段(field)、成员方法、类方法
  6. HH SaaS电商系统的仓储系统设计
  7. 怎么把word里面虚线变成实线_弱电不会制作cad图,花3分钟看完,只要会用WORD保证你能画出来...
  8. 位运算和进制转换,反码补码
  9. 有c基础学java多久_有c十十基础的自学java语言每天6小时要多长时间?
  10. _用WSL,MobaXterm,Cmder配置linux开发环境