2013-09-24 4 views
2

У меня проблема с моей программой. Он, кажется, замерзает, скорее всего, вызван циклом while.Замораживание при сопоставлении с образцом

Что я пытаюсь сделать, это подобрать и заменить комментарии Java. Итак, при написании комментария к блоку вы откроете этот комментарий с помощью /*. Если нет закрывающего конца (*/), программа занимает 5-6 секунд, где она заморожена, и вы не можете ее использовать. Я запускал это с еще большим количеством регулярных выражений и файлом с более чем 10 000 строк без проблем с производительностью, поэтому любой тип снижения производительности вызывает тревогу, но в одиночку 5-секундная задержка.

private static final String COMMENT_MATCHER = "(//.*)|(/\\u002A((\\s)|(.))*?\\u002A/)"; 

private String clearMatches(String code, final String regex) { 
    final Pattern pattern = Pattern.compile(regex); 
    final Matcher matcher = pattern.matcher(code); 
    while (matcher.find()) { 
     final String match = matcher.group(); 
     code = code.replace(match, CharBuffer.allocate(match.length()).toString()); 
    } 
    return code; 
} 

Я предполагаю, что этот вопрос лежит в ней найти много матчей и переборе всех из них, из-за паразитной звездочкой.

С уважением, Обичек.

+0

Я считаю, что вы могли бы помочь отладкам, делая подход два выстрела - один для многострочных комментариев и один для однострочных комментариев. Например, имеют две константы: SINGLE_LINE_COMMENT_MATCHER и MULTI_LINE_COMMENT_MATCHER, каждая со своим собственным регулярным выражением. – Meesh

+0

@Meesh совпадение соответствует комментариям хорошо, это просто, когда комментарии mutli-line не имеют конца. Который, когда вы печатаете их, вы сталкиваетесь. – Obicere

+1

Ваш шаблон может быть уменьшен до более читаемой (по крайней мере для меня) версии '' // [^ \ n] * | /[*].*?[*]/ "' если вы скомпилируете ее с помощью 'Pattern.DOTALL' флаг или добавить '(? s)' при запуске? – Pshemo

ответ

2

Ваши временные наблюдения не удивительны. Соответствие Java regexp может быть очень медленным (т. Е. O (2 ** n), если n - длина регулярного выражения) из-за обратного слежения. Иногда можно изменить регулярное выражение, чтобы избежать обратного отсчета, так что он будет быстрым.

Одна идея ускорения использует притяжательные кванторы, см. Их в http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html. Еще одна идея ускорения заключается в использовании меньшего числа операторов |.

Попробуйте это:

private static final String COMMENT_MATCHER = "(//.*+)|(?s)(/[*].*?[*]/)"; 
+0

Ничего себе, это сработало! Я не лучший с регулярными выражениями, и я не знал об этом, спасибо. – Obicere

4

Попробуйте это:

COMMENT_MATCHER = "//[^\r\n]*+|/[*](?:(?![*]/)[\\s\\S])*+[*]/"; 

, который должен значительно быстрее работать.

Быстрая ломка шаблона:

 

//     # match "//" 
[^\r\n]*+   # possessively match any chars other than line break chars 
|     # OR 
/[*]    # match "/*" 
(?:     # start non-capture group 
    (?![*]/)[\\s\\S] # match any char, only if "*/" is not ahead 
)*+     # end non-capture group and possessively repeat zero or more times 
[*]/    # match "*/" 

Смежные вопросы