Как получить хорошую производительность Regex в Java - PullRequest
2 голосов
/ 16 ноября 2009

Ниже приведен пример текста:

String id = "A:abc,X:def,F:xyz,A:jkl";

Ниже приведено регулярное выражение:

Pattern p = Pattern.compile("(.*,)?[AC]:[^:]+$");
if(p.matcher(id).matches()) {
  System.out.println("Hello world!")
}

При выполнении вышеприведенного кода должно быть напечатано Hello world !.

Можно ли изменить это регулярное выражение для увеличения производительности?

Ответы [ 4 ]

8 голосов
/ 16 ноября 2009

Поскольку я не вижу весь ваш код, я могу только предположить, что вы выполняете компиляцию шаблона внутри вашего цикла / метода / и т. Д. Одна вещь, которая может улучшить производительность - это компилировать на уровне класса, а не перекомпилировать шаблон каждый раз. Кроме этого, я не вижу больше, что вы могли бы изменить.

3 голосов
/ 16 ноября 2009
Pattern p = Pattern.compile(".*[AC]:[^:]+$");
if(p.matcher(id).matches()) {
  System.out.println("Hello world!")
}

Как вам кажется, вас интересует только, если строка заканчивается на A или C , за которой следует двоеточие и некоторые символы, которые не являются двоеточиями, вы можете просто использовать .* вместо (.*,)? (или вы действительно хотите захватить материал до последнего фрагмента?)

Если после двоеточия все написано строчными буквами, вы можете даже сделать

Pattern p = Pattern.compile(".*[AC]:[a-z]+$");

И если вы собираетесь сопоставить это несколько раз подряд (например, цикл), обязательно скомпилируйте шаблон вне цикла.

е, г

Pattern p = Pattern.compile(".*[AC]:[a-z]+$");
Matcher m = p.matcher(id);
while(....) {
  ...
  // m.matches()
  ...
  // prepare for next loop m.reset(newvaluetocheck);
}
1 голос
/ 16 ноября 2009

Перемещение Pattern создания экземпляров в конечное статическое поле ( erm, константа ), в текущем коде вы перекомпилируете по существу одинаковые Pattern каждый раз (нет, Pattern не делает ' ничего не кешировать!) Это должно дать вам заметное повышение производительности сразу.

0 голосов
/ 16 ноября 2009

Вам даже нужно использовать регулярные выражения?Кажется, что в тестируемом тесте нет большого разнообразия.

Если вам нужно использовать регулярное выражение, как уже говорили другие, компиляция его имеет смысл только один раз, и если вам нужно проверить только последний токенВы могли бы упростить регулярное выражение до: [AC]:[^:]{3}$.

Не могли бы вы использовать что-то подобное (непроверенный ...)?

private boolean isId(String id)
    {
        char[] chars = id.toCharArray();
        boolean valid = false;
        int length = chars.length;

        if (length >= 5 && chars[length - 4] == ':')
        {
            char fifthToLast = chars[length - 5];

            if (fifthToLast == 'A' || fifthToLast == 'C')
            {
                valid = true;

                for (int i = length - 1; i >= length - 4; i--)
                {
                    if (chars[i] == ':')
                    {
                        valid = false;
                        break;
                    }
                }
            }
        }

        return valid;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...