"Запускается с" быстрее, чем "indexOf"? - PullRequest
4 голосов
/ 30 июня 2009

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

Мне было интересно, быстрее ли startsWith, чем indexOf. Я экспериментировал с 2000 записями, но не нашел никакой разницы.

Ответы [ 7 ]

9 голосов
/ 30 июня 2009

startsWith нужно только проверить наличие в самом начале строки - она ​​выполняет меньше работы, поэтому она должна быть быстрее.

Я предполагаю, что ваши записи 2000 закончились за несколько миллисекунд (если таковые имеются). Всякий раз, когда вы хотите сравнить один подход с другим, старайтесь делать это в течение достаточного времени, чтобы различия во времени были значительными. Я считаю, что 10-30 секунд достаточно для значительных улучшений, но достаточно коротки, чтобы можно было многократно запускать тесты. (Если бы это было серьезное расследование, я бы, вероятно, попытался бы дольше. Большая часть моих тестов для развлечения.)

Также убедитесь, что у вас есть различные данные - indexOf и startsWith должны иметь примерно одинаковое время выполнения в случае, если indexOf возвращает 0 . Так что, если все ваши записи соответствуют шаблону, вы не правильно тестируете. (Я не знаю, так ли это было в ваших тестах - это просто то, на что нужно обратить внимание.)

7 голосов
/ 30 июня 2009

В общем, здесь действует золотое правило микрооптимизации:

«Мера, не угадай».

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

Запустите профилировщик над своим кодом и оптимизируйте этот вызов только тогда, когда вы можете измерить, что он замедляет работу. До тех пор, перейдите с более удобочитаемыми параметрами (в данном случае начинается с). Как только вы узнаете, что этот блок замедляет работу, попробуйте оба варианта и используйте тот, который быстрее. Полоскание. Повторите; -)

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

5 голосов
/ 30 июня 2009

Даже не глядя на источники, должно быть ясно, что запускается быстрее, по крайней мере, для больших строк и короткого шаблона:

Время выполнения a.startsWith (b) ограничено длиной b. После проверки не более первых символов b поиск завершен.

Время выполнения a.indexOf (b) больше (зависит от фактического алгоритма ). Каждый алгоритм имеет как минимум время выполнения в зависимости от длины a. Грубо говоря, вы можете сказать, что вам нужно посмотреть на каждого персонажа один раз, чтобы проверить, начинается ли паттерн с этой позиции.

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

2 голосов
/ 30 июня 2009

Возможно, если он не совпадает, он может перестать искать, тогда как indexOf нужно искать вхождения позже в строке.

1 голос
/ 30 июня 2009

начинается с ясности, чем indexOf == 0.

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

0 голосов
/ 30 июня 2009
public class Test
{
  public static void main(String args[]) {

    long value1 = System.currentTimeMillis();
    for(long i=0;i<100000000;i++)
    {
        "abcd".indexOf("a");
    }
    long value2 = System.currentTimeMillis();
    System.out.println(value2-value1);


    value1 = System.currentTimeMillis();
    for(long i=0;i<100000000;i++)
    {
        "abcd".startsWith("a");
    }
    value2 = System.currentTimeMillis();
    System.out.println(value2-value1);
  }
}

Протестировал его с этим куском кода и perf для стартов. Кажется, он лучше, по очевидной причине, что он не должен проходить через строку. Но в лучшем случае оба должны работать близко, в то время как в худшем случае запускается с всегда лучше, чем indexOf

0 голосов
/ 30 июня 2009

Вы упомянули, что набор данных, как ожидается, будет большим. Поэтому я готов поспорить, что многие исполнители зайдут в этот набор данных и обработают его в памяти. Это означает, что использование одного или другого не изменит производительность существенно. Но если это важно для вас, вы можете написать свой собственный метод startWith, который может быть значительно быстрее стандартных библиотечных методов или, по крайней мере, вы точно знаете, что делается.

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