Ответ 1
TL; DR Для простых подстрок
contains()
лучше всего, но только для соответствия целым словам. Правильное выражение, вероятно, лучше.
Лучший способ увидеть, какой метод более эффективен, - проверить его.
Вы можете использовать String.contains()
вместо String.indexOf()
, чтобы упростить код, не относящийся к регулярному выражению.
Для поиска разных слов регулярное выражение выглядит следующим образом:
apple|orange|pear|banana|kiwi
|
работает как OR
в регулярных выражениях.
Мой очень простой тестовый код выглядит следующим образом:
public class TestContains {
private static String containsWord(Set<String> words,String sentence) {
for (String word : words) {
if (sentence.contains(word)) {
return word;
}
}
return null;
}
private static String matchesPattern(Pattern p,String sentence) {
Matcher m = p.matcher(sentence);
if (m.find()) {
return m.group();
}
return null;
}
public static void main(String[] args) {
Set<String> words = new HashSet<String>();
words.add("apple");
words.add("orange");
words.add("pear");
words.add("banana");
words.add("kiwi");
Pattern p = Pattern.compile("apple|orange|pear|banana|kiwi");
String noMatch = "The quick brown fox jumps over the lazy dog.";
String startMatch = "An apple is nice";
String endMatch = "This is a longer sentence with the match for our fruit at the end: kiwi";
long start = System.currentTimeMillis();
int iterations = 10000000;
for (int i = 0; i < iterations; i++) {
containsWord(words, noMatch);
containsWord(words, startMatch);
containsWord(words, endMatch);
}
System.out.println("Contains took " + (System.currentTimeMillis() - start) + "ms");
start = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
matchesPattern(p,noMatch);
matchesPattern(p,startMatch);
matchesPattern(p,endMatch);
}
System.out.println("Regular Expression took " + (System.currentTimeMillis() - start) + "ms");
}
}
Результаты, которые я получил, были следующими:
Contains took 5962ms
Regular Expression took 63475ms
Очевидно, что тайминги будут различаться в зависимости от количества искомых слов и искомых строк, но contains()
, кажется, в ~ 10 раз быстрее, чем регулярные выражения для простого поиска, подобного этому.
Используя регулярные выражения для поиска строк внутри другой строки, вы используете кувалду, чтобы взломать гайку, поэтому я думаю, мы не должны удивляться, что она медленнее. Сохранять регулярные выражения, когда шаблоны, которые вы хотите найти, более сложны.
В одном случае, когда вы можете использовать регулярные выражения, если indexOf()
и contains()
не будут выполнять задание, потому что вы хотите только совместить целые слова, а не подстроки, например. вы хотите совместить pear
, но не spears
. Регулярные выражения хорошо справляются с этим случаем, так как они имеют концепцию границ слов.
В этом случае мы изменили бы наш шаблон на:
\b(apple|orange|pear|banana|kiwi)\b
\b
говорит, что соответствует только началу или концу слова, а скобки группируют выражения OR вместе.
Обратите внимание, что при определении этого шаблона в коде вам нужно избежать обратных косых черт с помощью другой обратной косой черты:
Pattern p = Pattern.compile("\\b(apple|orange|pear|banana|kiwi)\\b");