Это нормальное поведение регулярных выражений Java? - PullRequest
5 голосов
/ 25 ноября 2011


Я нашел это в некотором коде, который хотел оптимизировать.Вот фрагмент:

tempString = bigBuffer.replaceAll("\\n", "");
tempString = tempString.replaceAll("\\t", "");

Тогда я решил использовать регулярное выражение с умом и сделал это:

tempString = bigBuffer.replaceAll("[\\n\\t]", "");

Тогда друг сказал мне сделать это вместо:

tempString = bigBuffer.replaceAll("\\n|\\t", "");

Поскольку я хотел бы узнать результат своих изменений, я провел тест, чтобы проверить, была ли это хорошая оптимизация.Таким образом, результат с (версия Java "1.6.0_27") с первым кодом, являющимся ссылкой на 100%.

Для трубы это 121%, поэтому для выполнения задачи потребовалось больше времени.

Для квадратной скобки - 52%, поэтому для выполнения задачи потребовалось меньше времени.

Почему регулярное выражение ведет себя по-разному, где оно должно быть одинаковым?

Мартин

Ответы [ 2 ]

4 голосов
/ 25 ноября 2011

Первый фрагмент кода просматривает bigBuffer дважды, первый раз заменяя новые строки, а второй заменяет вкладки.

Второй фрагмент кода будет выполнять поиск в bigBuffer только один раз, проверяя, является ли каждый символ одним или другим.Это привело бы к скорости, заканчивающейся только в половине времени.

Фрагмент кода в третьем месте, вероятно, плохо скомпилирован, что приводит к особенно плохой версии алгоритма первого кода, хотя я не могу сказать наверняка, не изучив путь через компиляцию регулярного выражения.

Отличная работа по тестированию.Относительная синхронизация (в процентах) полезна, абсолютная синхронизация (миллисекунды или около того) - нет.

2 голосов
/ 25 ноября 2011

Вообще говоря, класс символов ([abc]) имеет тенденцию быть более эффективным, чем эквивалентное чередование (a|b|c), поэтому я не знаю, почему ваш друг предложил бы это. Но в Java классы символов, которые соответствуют только символам из репертуара Latin1 (т.е. первые 256 кодовых точек Юникода), дополнительно оптимизируются. Вероятно, поэтому вы видите такую ​​большую разницу между вторым и третьим методами.

Опять же, это только на Java. В Perl я бы ожидал, что разница между чередованием и классом символов будет незначительной, поскольку это гораздо более зрелая реализация. И в grep, вероятно, будет трудно измерить разницу, независимо от того, какой из трех подходов вы использовали - это просто так быстро.

Но, как правило, если у вас есть выбор между использованием класса символов или альтернативой, вы должны предпочесть класс символов. Это может быть не быстрее, но определенно не будет медленнее. Неправильное использование чередования может иметь катастрофические последствия для производительности.

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