【问题标题】:java8 regex match very slowjava8 正则表达式匹配非常慢
【发布时间】:2018-11-26 22:43:57
【问题描述】:

我有一个正则表达式 ^[a-z]+([a-z0-9-]+)*[a-z0-9]+$ 用于验证。

String src = "alfjaldfjaldmflajdflakclaldkfjaldjlad,fl.adc.aldjfal";
src.matches("^[a-z]+([a-z0-9-]+)*[a-z0-9]+$");

但是,matches 没有响应。 你知道快速正则表达式吗??

【问题讨论】:

  • 您正在使用贪婪的匹配器 - 结果是 - 很慢。 Read here 了解更多信息。
  • @Lino 预编译的正则表达式通常非常快。这里的这个可能需要相当多的回溯,这很慢。

标签: java regex string performance


【解决方案1】:

只是详细说明@OldCurmudgeon 提供的答案

Pattern pattern = Pattern.compile("^[a-z][a-z0-9-]*[a-z0-9]$");
String src = "alfjaldfjaldmflajdflakclaldkfjaldjlad,fl.adc.aldjfal";
long start = System.nanoTime();
src.matches("^[a-z]+([a-z0-9-]+)*[a-z0-9]+$");
long end1 = System.nanoTime();
src.matches("^[a-z]+[a-z0-9-]*[a-z0-9]+$");
long end2 = System.nanoTime();
src.matches("^[a-z][a-z0-9-]*[a-z0-9]$");
long end3 = System.nanoTime();
pattern.matcher(src).matches();
long end4 = System.nanoTime();
System.out.println((end1 - start)/1000);
System.out.println((end2 - end1)/1000);
System.out.println((end3 - end2)/1000);
System.out.println((end4 - end3)/1000);

以微秒为单位的输出

14377
1130
190
112

以下非正则表达式方法只需 10 微秒。

private static boolean matches(String str)
{
    if (str.length() < 2)
    {
        return false;
    }
    char first = str.charAt(0);
    if (!(first >= 'a' && first <= 'z'))
    {
        return false;
    }
    char last = str.charAt(str.length() - 1);
    if (!(last >= 'a' && last <= 'z') && !(last >= '0' && last <= '9'))
    {
        return false;
    }
    for (int i = 0; i < str.length() - 2; i++)
    {
        char ch = str.charAt(i + 1);
        if (!(ch >= 'a' && ch <= 'z') && !(ch >= '0' && ch <= '9') && ch != '-')
        {
            return false;
        }
    }
    return true;
}

【讨论】:

    【解决方案2】:

    你的问题在这里:([a-z0-9-]+)*

    您正在尝试匹配一次或多次 x 0 次或多次。这没有意义。

    改用 ([a-z0-9-]+) 或 ([a-z0-9-]*) 以适合您的要求。

    另外 - 您可以使用以下方法编译模式:

    Pattern compiled = Pattern.compile(regex);
    

    这会有所帮助,但不是您的问题。

    【讨论】:

    • ([a-z0-9-]+)* 应该改为([a-z0-9-]*) 而不是([a-z0-9-]+),但无论如何都要+1!通过这样做,您强制该字符类 [a-z0-9-] 至少存在一次,以前不是这样!
    • 第一部分和第三部分也可以简化。正则表达式可以是 ^[az][a-z0-9-]*[a-z0-9]$ 注意第一和第三部分没有 + 因为这是第二部分处理的任何方式。
    猜你喜欢
    • 2019-01-13
    • 2020-06-21
    • 2012-08-13
    • 2014-05-04
    • 2021-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多