正则表达式和if比较哪个更快 - Java

11

我有两个选择,一个是制作正则表达式,另一个是用if比较。

如果比较

if (!(modoImpressao.equals("IMPRESSORA") || 
   modoImpressao.equals("PDF") || modoImpressao.equals("AMBOS")))

正则表达式匹配

if (!Pattern.compile("(IMPRESSORA)|(PDF)|(AMBOS)",Pattern.DOTALL).matcher(modoImpressao).find()){
            throw new EspdNeverStopParametroInvalidoException(TspdConstMessages.IMPRIMIR_PARAMETRO_MODOIMPRESSAO_INVALIDO,"TspdImprimirNFCe");
        }

哪一个更快?


你的DOTALL选项是无用的。 - Casimir et Hippolyte
普通的字符串比较/索引查找,总是比正则表达式更快。当你有一个模式时,使用正则表达式。 - nhahtdh
编写一个简短的程序,在循环中运行几次,并确保结果,而不是依赖猜测。 - theglauber
1
代码存在两个问题:(A) 两个代码片段在语义上不同,第一个检查字符串是否相等,而第二个检查主题字符串是否包含模式。然后 (B) 正则表达式包含三个不必要的括号对,它们会造成(小)性能损失,因为它们声明了“捕获组”。 - Arno Unkrig
5个回答

19

第一个代码片段很可能更快,因为它不需要解析正则表达式并执行匹配操作。另一种替代方法是:

if (Arrays.asList("IMPRESSORA", "PDF", "AMBOS").contains(modoImpressao)

这段代码的速度应该与您第一个代码片段相比没有太大差异,但更易读和简洁。

正则表达式很好用,但只有在必要时才使用它们。这种情况绝对不需要使用正则表达式;您所做的就是与字面字符串进行比较。

有一句老话来自Jamie Zawinski:

有些人遇到问题时会想,“我知道了,我将使用正则表达式。”现在他们有两个问题了。


1
很好!但是可以尝试使用contains而不是equals。在某些情况下,可以忽略解析正则表达式的时间,因为它可以是static的。你的答案不错,但实际上并没有回答关于这个主题的一些常见问题。 - Dherik

3
如果您只使用正则表达式一次,它很可能会更慢,特别是当您使用find时,实际上是指与您的问题中的matches相同。
当您保留已编译的Pattern并多次使用它时,它有可能比多个等号更快。
然而,这取决于上下文。如果您测试的所有String都是文字,并且匹配比失败更有可能,则String.equals将快得多,因为它在实例相同时绕过测试。
最快的解决方案是根据候选String的易于检查的属性进行预选择,该属性对于所有String都不同,例如某个位置的charlength,并为所选String执行单个equals。在您的情况下,第一个字符和长度都是合适的。在这种情况下,我更喜欢长度,因为您必须在访问字符之前检查长度以防止空Strings
首选使用length的变体:
nomatch:
{
  switch(modoImpressao.length())
  {
    case 3: if(modoImpressao.equals("PDF")) break nomatch; break;
    case 5: if(modoImpressao.equals("AMBOS")) break nomatch; break;
    case 10: if(modoImpressao.equals("IMPRESSORA")) break nomatch; break;
  }
  throw new EspdNeverStopParametroInvalidoException(
    TspdConstMessages.IMPRIMIR_PARAMETRO_MODOIMPRESSAO_INVALIDO,
    "TspdImprimirNFCe");
}
// one of the three values matched

使用第一个char变量的变体:
nomatch:
{
  if(modoImpressao.length()>0) switch(modoImpressao.charAt(0))
  {
    case 'P': if(modoImpressao.equals("PDF")) break nomatch; break;
    case 'A': if(modoImpressao.equals("AMBOS")) break nomatch; break;
    case 'I': if(modoImpressao.equals("IMPRESSORA")) break nomatch; break;
  }
  throw new EspdNeverStopParametroInvalidoException(TspdConstMessages.IMPRIMIR_PARAMETRO_MODOIMPRESSAO_INVALIDO,"TspdImprimirNFCe");
}
// one of the three values matched

2

使用正则表达式在检查大字符串时比使用if语句(例如在for循环中)更快,以满足您的要求。

如果您使用正则表达式来匹配非常小的文本和小的模式,并且没有这样做是因为匹配函数.find()比普通if语句或switch语句慢。


0

从Java 7开始,您可以使用“字符串开关”,它们非常快速,因为它们基于字符串的哈希值。


0

如果你想要查找模式字符串,而不是像第二个代码片段中检查相等性,那么使用像Boyer-Moore-Horspool这样的高级字符串查找算法可能会提高性能。虽然自行实现不容易,但许多正则表达式库(包括java.util.regex)都内置了它,因此在这种情况下,使用正则表达式进行搜索可能会更快。

如果“find()”速度是您主要关注的问题,您还可以看看github.com/aunkrig/lfr。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接