Подтвердить что ты не робот

Regex VS содержит. Лучшее представление?

Я хочу сравнить строку URI по различным шаблонам в java, и я хочу получить самый быстрый код.

Должен ли я использовать:

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

Или что-то вроде:

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

Обратите внимание, что у меня может быть намного больше uri, и этот метод вызывается очень часто.

Каков наилучший ответ между моими выборами?

4b9b3361

Ответ 1

Они оба достаточно быстро, чтобы закончить, прежде чем вы это узнаете. Я бы выбрал тот, который можно читать легче.

Ответ 2

Если вы собираетесь использовать регулярное выражение, создайте его и используйте один и тот же объект Pattern:

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

Вам действительно нужно ". *" на каждом конце? Я бы не ожидал, что это потребуется, если вы используете Matcher.find().

Что быстрее? Самый простой способ узнать это - измерить его по некоторым выборочным данным - с максимально возможными реалистичными образцами. (Быстрое решение может очень сильно зависеть от

Вы уже уверены, что это узкое место? Если вы уже измерили код достаточно, чтобы узнать, что это узкое место, я удивлен, что вы уже не пробовали оба. Если вы еще не подтвердили, что это проблема, это первое, что нужно сделать, прежде чем беспокоиться о "самом быстром коде".

Если это не узкое место, я бы выбрал вариант без регулярного выражения, если вы не наркоман регулярного выражения. Регулярные выражения очень мощные, но также очень легко ошибиться.

Ответ 3

Я сделал тест, и его быстрее использовать. Как сказал Эван Тодд, они оба достаточно быстро, чтобы не беспокоиться об этом.

Ответ 4

Я бы ожидал, что contains() будет быстрее, так как ему не придется компилировать и выполнять итерацию (относительно) сложного регулярного выражения, а просто искать последовательность символов.

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

Кроме того, известно ли это, что вы причиняете вам горе (по производительности)? Если нет, я бы не стал слишком беспокоиться об этом и выбирал наиболее подходящее решение для ваших требований, независимо от проблем с производительностью. Преждевременная оптимизация вызовет у вас чрезмерное количество горя, если вы позволите!

Ответ 5

UPDATE: Я знаю, что это не лучший тестовый код, и для каждого случая есть несколько способов его оптимизации.

То, что я хотел достичь, было для обычного разработчика, который будет использовать более простые способы делать вещи, а это не эксперт 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));


}

Ответ 6

Если бит, который вы пытаетесь сопоставить, всегда находится в начале или в конце или каким-то другим образом предсказуем: ни!

Например, если URL-адреса похожи на http://example.com/br/fab или http://example.com/br/err, тогда вы можете хранить "br/fab" и "br/err" и т.д. в HashSet или аналогичном, а затем задавать входящий URL-адрес, отрубать последнюю часть и запрашивать Установите, чтобы увидеть, содержит ли он это. Это будет масштабироваться лучше, чем любой метод, который вы дали (с помощью HashSet он не должен замещать записи медленнее, независимо от того, сколько их есть).

Если вам нужно сопоставлять подстроки, появляющиеся в произвольных местах... это зависит от того, что вы подразумеваете под "намного больше". Одна вещь, которую вы должны делать, независимо от специфики проблемы, - это попробовать и сравнить их!

Ответ 7

его намного быстрее, если вы используете 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) и вычисляет выражение.

Матчи - очень дорогостоящая вещь при обработке большого объема данных.