2015-02-06 2 views
-1

Я пытаюсь создать перечисление, которое содержит строку регулярных выражений, убедившись, что шаблон только компилируется один раз, потому что pattern compilation is expensive, и я многократно использую тот же шаблон. Я пытаюсь создать динамически скомпилированный объект Pattern в зависимости от выбранного типа перечисления. Однако я застрял в следующем. Можете ли вы любезно предоставить некоторые рекомендации или предложить лучший способ добиться этого?Java - regex pattern compilation best practice (with enum)

public enum LOG_SCANNER{ 
    FOO_STRING(".*XXXX$"), 
    BAR_STRING(".*YYYY.*"), 
    ; 

    static Pattern p; 
    static { 
     p = Pattern.compile(regex); // Compilation failes here 

    } 


    String regex; 
    private LOG_NAME_MATCHER(String regex) { 
     this.regex = regex; 
    } 


} 

редактировать: Пожалуйста, обратите внимание, что я не использую регулярное выражение для поиска чего-то, что может быть достигнуто с String.endsWith() или .Contains(). (". * XXXX $") является просто примером.

+0

Помимо устранения проблем с компиляцией, ознакомьтесь с http://stackoverflow.com/questions/2423376/java-initialization-order-issue-static-vs-instance-fields и смежными вопросами. –

+4

Вы слишком задумываетесь об этом. Если вы используете один и тот же шаблон много раз, поместите его в отдельный класс utils/константы, а затем используйте его. – TheLostMind

+2

@ TheLostMind На самом деле, это слишком завышено. Хорошее слово! – laune

ответ

2

насчет:

public enum LogNameMatcher{ 
    FOO_LOG(".*Foo\\.log$"), 
    BAR_LOG(".*bar\\.log$"); 

    private final Pattern pattern; 

    private LogNameMatcher(final String regex) { 
     this.pattern = Pattern.compile(regex); 
    } 

    public Pattern getPattern() { return this.pattern; } 
} 

или (как указано в комментариях)

public final class LogNameMatcher { 
    public static final Pattern FOO_LOG = Pattern.compile(".*Foo\\.log$"); 
    public static final Pattern BAR_LOG = Pattern.compile(".*bar\\.log$"); 

    private LogNameMatcher() { 
     // util class 
    } 
} 
+0

Простой 'stringToMatch.endsWith (« Foo.log »)' и т. Д. Будет достаточным и намного более эффективным. – laune

+0

@laune Согласен (спасибо за редактирование btw) –

0

После обсуждения, альтернатива может быть, чтобы собрать образцы в некоторой коллекции:

List<Pattern> patterns = new ArrayList<>(); 
for(String ps: new String[]{ "...Foo...", "...bar...",... }){ 
    patterns.add(Pattern.compile(ps)); 
} 

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

Кроме того, вы можете сделать

String[] patstrs = new String[]{ "(.*Foo.*)", "(.*bar.*)", "(.blech.)"}; 
String ap = String.join("|", patstrs); 
Pattern p = Pattern.compile(ap); 
String t = "a Foo is here"; 
Matcher m = p.matcher(t); 
if(m.matches()){ 
    for(int i = 1; i <= m.groupCount(); i++){ 
     if(m.group(i) != null){ 
      System.out.println("#" + i + " matches"); 
     } 
    } 
} 

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