Java: регулярные выражения против операторов if

У меня есть массив, и я хочу найти в нем строки, начинающиеся с "test" (например); каков наиболее эффективный способ поиска этих установленных префиксов? Регулярные выражения или операторы if?

Регулярное выражение:

    boolean found = false;
    for (String line: ArrayList){
                Pattern pattern = 
                Pattern.compile("^test"); //regex

                Matcher matcher = 
                pattern.matcher(line);


                while (matcher.find()) {
                    found = true;
                }
                if(found){
                    doSomething();
                         } 
                    }
                }

если Заявление:

for (String line : ArrayList) {
       if (line.startsWith("test"){
            doSomething();
            }

Что наиболее эффективно?

Какой метод наиболее эффективен для более длинных строк?

Если я хочу найти строки, начинающиеся с «test», но затем только те, у которых есть «foo» после «test», какой метод лучше?

Если Regex является ответом, каков правильный синтаксис для того, чтобы сказать, что он начинается с «test», за которым следует «foo» или «bar», но не оба?


person Community    schedule 12.07.2012    source источник
comment
Регулярное выражение для этого IMO слишком много...   -  person Francisco Spaeth    schedule 12.07.2012
comment
Небольшое замечание: даже если здесь имеет смысл использовать регулярные выражения, шаблон следует компилировать вне цикла.   -  person Thomas    schedule 12.07.2012
comment
если у вас есть случаи, когда один блок должен отвечать за большее количество префиксов, загляните в StringUtils.startsWithAny(String string, String[] searchStrings)   -  person Francisco Spaeth    schedule 12.07.2012


Ответы (6)


Просто используйте startsWith. Regex немного излишен, если вы не хотите принимать String с начальными пробелами.

startsWith может работать с "test" или даже с "testfoo". Если вы имеете в виду, что "foo" может появиться в любом месте ввода после "test" (то есть "testokokokfoonothing"), то здесь следует использовать регулярное выражение.

Ваш код для версии регулярного выражения можно сократить до:

for (String line: ArrayList){
    if (line.matches("^test.*") {
        doSomething();
    }
}

matches() проверьте, соответствует ли весь ввод регулярному выражению, поэтому необходимо немного изменить регулярное выражение. Приведенный выше код немного медленнее, так как Pattern перекомпилируется.

person nhahtdh    schedule 12.07.2012

4 строки кода по сравнению с 16 строками? Неважно, что работает быстрее, 4-строчная версия более эффективна в написании и обслуживании.

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

person Duncan    schedule 12.07.2012
comment
Что происходит с каждым из них, если я хочу найти больше, чем просто foo (около 20 разных суффиксов) или больше, чем просто test? Я задал этот вопрос, потому что получил ошибки OutOfMemory для операторов if. - person ; 12.07.2012
comment
Если у вас есть что-то более сложное для сопоставления, то может подойти что-то вроде регулярного выражения, но это будет зависеть от того, что вы действительно делаете. На вопрос, который вы задали, ответ заключается в том, чтобы просто использовать line.startsWith(...) - person Duncan; 12.07.2012

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

person Louis Wasserman    schedule 12.07.2012

Мне нравятся операторы ЕСЛИ. Лично я избегаю Regex, если это вообще возможно. Они становятся сложными и трудными для кодирования. Когда дело доходит до кодирования, одной из самых важных вещей является удобство сопровождения, а Regex этого не обеспечивает.

Оставайтесь с оператором if.

person BlackHatSamurai    schedule 12.07.2012
comment
Ну, это зависит. Есть случаи, которые легче кодировать и читать с помощью регулярных выражений, если вы их понимаете. - person Thomas; 12.07.2012
comment
Возможно, но, как вы сказали, ЕСЛИ вы их понимаете. При написании кода вы не всегда его поддерживаете; поэтому вы хотите использовать то, что будет проще для всех. Если вы единственный, кто знает, как использовать Regex, вы будете единственным, с кем будет легко работать, а это не очень хорошая практика. - person BlackHatSamurai; 12.07.2012

Вы должны предпочесть startWith(). Он более идиоматичен, лаконичен, и вряд ли вы сможете реализовать что-то быстрее, особенно с java.util.regex, так как относительно легко написать неэффективное регулярное выражение.

Как правило, вы должны использовать java.util.regex только тогда, когда стандартных методов для объекта String будет недостаточно.

Несколько замечаний по вашему коду Regex: если вы собираетесь использовать регулярное выражение для чего-то другого, вам не следует запускать Pattern.compile внутри вашего цикла. вы можете еще больше упростить свой код, сказав:

if (matcher.find()) {
    doSoemthing();
}
person Paul Sanwald    schedule 12.07.2012

Первое, что вам нужно сделать: поместить Pattern pattern = Pattern.compile("^test"); //regex вне for, потому что компиляция съедает время, и это нужно сделать один раз и только один раз.

   Pattern pattern = Pattern.compile("^test.*"); //regex
   for (String line: ArrayList){
       if(patter.matches(line)){
            oSomething();
       }
   }
person cl-r    schedule 13.07.2012