Бесконечный l oop при использовании Matcher в Java - PullRequest
0 голосов
/ 24 февраля 2020

Я изучаю регулярное выражение и у меня есть этот фрагмент кода:

private static final String FILE_BEGINNING_PATTERN = "^(,Share %)";

public static void main(String[] args) {
    String str = ",Share %,\"Date Purchased\",Display Name,Address,Phone,Fax,Mobile,Email,";

    Matcher beginningFileMatcher = Pattern.compile(FILE_BEGINNING_PATTERN).matcher(str);
    if (beginningFileMatcher.find()) {
        System.out.println("Regex match!");
    }

    // find() method starts at the beginning of this matcher's region, or, if
    // a previous invocation of the method was successful and the matcher has
    // not since been reset, at the first character not matched by the previous
    // match.
    //

    int count = 0;
    while (beginningFileMatcher.find()) { // find not match, we need beginningFileMatcher.reset() but its not 
        // thread-safe.
        count++;
        System.out.println("COUNT ++++++++++++++ :" + count);
    }
}

попробуйте другой способ:

private static final String FILE_BEGINNING_PATTERN = "^(,Share %)";

public static void main(String[] args) {
    String s = ",Share %,\"Date Purchased\",Display Name,Address,Phone,Fax,Mobile,Email,";
    Pattern beginningFilePattern = Pattern.compile(FILE_BEGINNING_PATTERN);
    Matcher matcher = beginningFilePattern.matcher(s);

    if (beginningFilePattern.matcher(s).find()) {
        System.out.println("Thread-safe regex match!.");
    }

    int countCount = 0;
    while (beginningFilePattern.matcher(s).find()) { //this cause infinite loop while matcher.find() done as 
        // expected result! Why?
        countCount++;
        System.out.println("COUNT ++++++++++++++ :" + countCount);
    }
}

Я уже комментировал эту проблему в этом фрагменте, как указано выше. Есть кто-нибудь, кто может объяснить, почему? Большое вам спасибо!

Ответы [ 4 ]

4 голосов
/ 24 февраля 2020

Проблема в том, что вы создаете новый экземпляр Matcher каждый раз в состоянии if и while l oop блоках здесь:

if (beginningFilePattern.matcher(s).find()) {

и здесь:

while (beginningFilePattern.matcher(s).find())

При создании нового экземпляра Matcher вы теряете предыдущее состояние этого состояния и каждый раз начинаете операцию сопоставления.

Также обратите внимание на удаление условия if перед while l oop чтобы получить count право.

Вы можете использовать этот код, чтобы исправить это:

String str = ",Share %,\"Date Purchased\",Display Name,Address,Phone,Fax,Mobile,Email,";

Matcher beginningFileMatcher = Pattern.compile(FILE_BEGINNING_PATTERN).matcher(str);

// find() method starts at the beginning of this matcher's region, or, if
// a previous invocation of the method was successful and the matcher has
// not since been reset, at the first character not matched by the previous
// match.
//

int count = 0;
while (beginningFileMatcher.find()) { // find not match, we need beginningFileMatcher.reset() but its not 
    if (count == 0)
        System.out.println("Regex match!");
    // thread-safe.
    count++;
    System.out.println("COUNT ++++++++++++++ :" + count);
}

//try another way.
String s = ",Share %,\"Date Purchased\",Display Name,Address,Phone,Fax,Mobile,Email,";
Pattern beginningFilePattern = Pattern.compile(FILE_BEGINNING_PATTERN);
Matcher matcher = beginningFilePattern.matcher(s);

int countCount = 0;
while (matcher.find()) { // make sure to use matcher object
    if (countCount == 0)
        System.out.println("Thread-safe regex match!");
    countCount++;
    System.out.println("COUNT ++++++++++++++ :" + countCount);
} 
1 голос
/ 24 февраля 2020

Каждая версия вашего кода имеет свою проблему.

Для версии 2 (inifinite l oop): вы создаете совпадение в l oop. Это означает, что на каждой итерации будет появляться новый сопоставитель, начиная с начала вашей строки. Таким образом, вызов find всегда будет возвращать один и тот же результат, если таковой имеется.

Ваше первое решение - это то, что вам нужно сделать, один раз создать средство сравнения, а затем использовать его, вызывая find в * 1036. *.

Проблема в том, что вы звоните find в 2 разных местах. Сначала в блоке if, чтобы увидеть, есть ли совпадения в вашей строке, затем в l oop.

Что, если строка содержит только 1 результат поиска?

  • Результат возвращается в блоке if
  • countCount установлен на 0
  • В то время как l oop пытается найти следующий матч, но его нет
  • код печатает COUNT : 0

Если вы не сбрасываете совпадения перед циклом, вам нужно посчитать результат из блока if в ваш счетчик. Вот решение с минимальными изменениями:

final static String FILE_BEGINNING_PATTERN = "^(,Share %)";

public static void main(String[] args) {
    String str = ",Share %,\"Date Purchased\",Display Name,Address,Phone,Fax,Mobile,Email,";

    Matcher beginningFileMatcher = Pattern.compile(FILE_BEGINNING_PATTERN).matcher(str);

    int count = 0;
    if (beginningFileMatcher.find()) {
        System.out.println("Regex match!");
        count++; // already a match, increment the counter
    }

    while (beginningFileMatcher.find()) { 
        count++;
        System.out.println("COUNT ++++++++++++++ :" + count);
    }
}

Другим способом было бы удалить блок if и использовать только while l oop.

0 голосов
/ 24 февраля 2020

Я думаю, что проблема в том, что когда вы вызываете beginningFilePattern.matcher(s).find(), вы создаете новый экземпляр соответствия в условии while. Каждый из этих новых сопоставителей будет проверять снова с самого начала, а не пытаться найти следующее вхождение. Вы должны попытаться обезопасить вашу reset() угрозу вызова, но сохранить тот же экземпляр соответствия.

0 голосов
/ 24 февраля 2020

Вы можете Сброс сопоставления ()

Сброс этого сопоставления.
Сброс сопоставления отбрасывает всю его явную информацию о состоянии и устанавливает его позицию добавления равной нулю. Регион matcher установлен в регион по умолчанию, который является всей его последовательностью символов. Привязка и прозрачность границ области этого сопоставителя не затрагиваются.

Если вы хотите, чтобы поток был безопасным, поместите его в synchronize block

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