正则表达式VS包含。 最棒的表演?

我想在java中比较不同模式的URI字符串,我想要尽可能快的代码。

我应该使用:

if(uri.contains("/br/fab") || uri.contains("/br/err") || uri.contains("/br/sts") 

或类似的东西:

 if(uri.matches(".*/br/(fab|err|sts).*")) 

请注意,我可以使用更多uri,并且经常调用此方法。

我的选择之间最好的答案是什么?

在你知道它们之前,它们都足够快。 我会选择一个你可以更容易阅读的那个。

如果您要使用正则表达式,请预先创建它并重用相同的Pattern对象:

 private static final Pattern pattern = Pattern.compile(".*/br/(fab|err|sts).*"); 

你真的需要两端的“。*”吗? 如果你使用Matcher.find() ,我不希望它是必需的。

哪个更快? 最简单的方法是根据一些样本数据对其进行测量 – 尽可能采用真实的样本。 (最快的解决方案可能很好地依赖于

您是否已经确定这是一个瓶颈? 如果你已经测量了足够的代码以发现它是一个瓶颈,我很惊讶你们还没有尝试过两者。 如果您还没有确认这是一个问题,那么在担心“最快的代码可能”之前,这是首先要做的事情。

如果它不是瓶颈,我个人会选择非正则表达版本,除非你是一个正则表达式的瘾君子。 正则表达式非常强大,但也很容易出错。

我做了一个测试,使用包含更快。 正如Ewan Todd所说,他们都足够快,不会那么烦。

我希望contains()更快,因为它不必编译和迭代(相对)复杂的正则表达式,而只是寻找一系列字符。

但是(与所有优化一样)你应该衡量这一点。 您的特定情况可能会或多或少地影响结果。

此外,这是否会导致你的悲伤(表现)? 如果没有,我不会太担心,并且无论性能问题如何,都可以根据您的要求选择最合适的解决方案。 如果你愿意的话, 过早的优化会让你产生过多的悲伤!

更新:我知道这不是最好的基准代码,对于每种情况,有几种方法可以优化它。

我想要实现的是,对于将使用更简单的处理方式且不是JVM专家的常规开发人员来说,这是使用它的“常见”方式,所以在这里。

原版的:

以下代码生成以下输出

  contains took: 70 matches took: 113 matches with pre pattern took: 419 

测试类

 public class MatchesTester { public static void main(String[] args) { String typeStr = "Nunc rhoncus odio ac tellus pulvinar, et volutpat sapien aliquet. Nam sed libero nec ex laoreet pretium sed id mi. Aliquam erat volutpat. Aenean at erat vitae massa iaculis mattis. Quisque sagittis massa orci, sit amet vestibulum turpis tempor a. Etiam eget venenatis arcu. Nunc enim augue, pulvinar at nulla ut, pellentesque porta sapien. Maecenas ut erat id nisi tincidunt faucibus eget vel erat. Morbi quis magna et massa pharetra venenatis ut a lacus. Vivamus egestas vitae nulla eget tristique. Praesent consectetur, tellus quis bibendum suscipit, nisl turpis mattis sapien, ultrices mollis leo quam eu eros.application/binaryNunc rhoncus odio ac tellus pulvinar, et volutpat sapien aliquet. Nam sed libero nec ex laoreet pretium sed id mi. Aliquam erat volutpat. Aenean at erat vitae massa iaculis mattis. Quisque sagittis massa orci, sit amet vestibulum turpis tempor a. Etiam eget venenatis arcu. Nunc enim augue, pulvinar at nulla ut, pellentesque porta sapien. Maecenas ut erat id nisi tincidunt faucibus eget vel erat. Morbi quis magna et massa pharetra venenatis ut a lacus. Vivamus egestas vitae nulla eget tristique. Praesent consectetur, tellus quis bibendum suscipit, nisl turpis mattis sapien, ultrices mollis leo quam eu eros."; int timesToTest = 10000; long start = System.currentTimeMillis(); int count = 0; //test contains while(count < timesToTest){ if (typeStr.contains("image") || typeStr.contains("audio") || typeStr.contains("video") || typeStr.contains("application")) { //do something non expensive like creating a simple native var int a = 10; } count++; } long end = System.currentTimeMillis(); System.out.println("contains took: "+ (end - start)); long start2 = System.currentTimeMillis(); count = 0; while(count < timesToTest){ if (typeStr.matches("(image|audio|video|application)")) { //do something non expensive like creating a simple native var int a = 10; } count++; } long end2 = System.currentTimeMillis(); //new var to have the same cost as contains System.out.println("matches took: "+ (end2 - start2)); long start3 = System.currentTimeMillis(); count = 0; Pattern pattern = Pattern.compile("(image|audio|video|application)"); while(count < timesToTest){ if (pattern.matcher(typeStr).find()) { //do something non expensive like creating a simple native var int a = 10; } count++; } long end3 = System.currentTimeMillis(); //new var to have the same cost as contains System.out.println("matches with pre pattern took: "+ (end3 - start3)); } 

如果你想要匹配的位总是在开头或结束,或者以某种其他方式可预测,那么:既不是!

例如,如果url一直是http://example.com/br/fab或http://example.com/br/err ,那么您可以存储“br / fab”和“br / err”等在HashSet或类似的,然后给出一个传入的URL,切断它的最后一部分,并查询Set以查看它是否包含它。 这将比你给出的任何一种方法都更好地扩展(使用HashSet,无论有多少,它都应该不会更慢地查找条目)。

如果你确实需要匹配出现在任意位置的子串…它取决于你的意思是“更多”。 无论问题的具体细节如何,你应该做的一件事就是尝试并对它们进行基准测试!

如果你使用indexOf(),它会快得多。

 if(uri.indexOf("/br/fab")>-1 || uri.indexOf("/br/err")>-1 || uri.indexOf("/br/sts") >-1 ) { your code. } 

而且contains()的问题是在内部创建一个Matcher(java.util.regex.Matcher)对象并对表达式进行evalated。

如果处理大量数据,Matcher是一件非常昂贵的事情。