Рубрики
Без рубрики

Разница между Java Matcher find() и matches()

Узнайте о различиях между методами find() и matches() класса Matches.

Автор оригинала: baeldung.

1. Обзор

При работе с регулярными выражениями в Java мы обычно ищем последовательность символов для заданного шаблона . Чтобы облегчить это, API регулярных выражений Java предоставляет класс Matcher , который мы можем использовать для сопоставления данного регулярного выражения с текстом.

Как правило, мы почти всегда хотим использовать один из двух популярных методов класса Matcher :

  • находить()
  • спички()

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

2. Метод find()

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

Давайте представим, что мы хотим найти предоставленную строку “до свидания 2019 и добро пожаловать 2020” только для четырехзначных чисел.

Для этого мы будем использовать шаблон “\\d\\d\\d\\d” :

@Test
public void whenFindFourDigitWorks_thenCorrect() {
    Pattern stringPattern = Pattern.compile("\\d\\d\\d\\d");
    Matcher m = stringPattern.matcher("goodbye 2019 and welcome 2020");

    assertTrue(m.find());
    assertEquals(8, m.start());
    assertEquals("2019", m.group());
    assertEquals(12, m.end());
    
    assertTrue(m.find());
    assertEquals(25, m.start());
    assertEquals("2020", m.group());
    assertEquals(29, m.end());
    
    assertFalse(m.find());
}

Как у нас есть два случая в этом примере– 2019 и 2020 – метод find() дважды вернет true , и как только он достигнет конца области соответствия, он вернет false .

Как только мы найдем какое-либо совпадение, мы можем использовать такие методы, как start () , group () и end () , чтобы получить более подробную информацию о совпадении , как показано выше.

Метод start() даст начальный индекс совпадения, end() вернет последний индекс символа после окончания совпадения, а group() вернет фактическое значение совпадения .

3. Метод find(int)

У нас также есть перегруженная версия метода find — find(int) . Он принимает начальный индекс в качестве параметра и рассматривает startindex в качестве отправной точки для поиска вхождений в строке .

Давайте посмотрим, как использовать этот метод в том же примере, что и раньше:

@Test
public void givenStartIndex_whenFindFourDigitWorks_thenCorrect() {
    Pattern stringPattern = Pattern.compile("\\d\\d\\d\\d");
    Matcher m = stringPattern.matcher("goodbye 2019 and welcome 2020");

    assertTrue(m.find(20));
    assertEquals(25, m.start());
    assertEquals("2020", m.group());
    assertEquals(29, m.end());  
}

Поскольку мы предоставили начальный индекс 20 , мы видим, что в настоящее время найдено только одно вхождение — 2020, которое происходит, как и ожидалось, после этого индекса . И, как в случае с find() , мы можем использовать такие методы, как start() , group () и end () , чтобы извлечь более подробную информацию о совпадении.

4. Метод matches()

С другой стороны, метод |/matches() пытается сопоставить всю строку с шаблоном .

В том же примере matches() вернет false :

@Test
public void whenMatchFourDigitWorks_thenFail() {
    Pattern stringPattern = Pattern.compile("\\d\\d\\d\\d");
    Matcher m = stringPattern.matcher("goodbye 2019 and welcome 2020");
 
    assertFalse(m.matches());
}

Это связано с тем, что он попытается сопоставить “\\d\\d\\d\\d” со всей строкой ” до свидания 2019 и добро пожаловать 2020″в отличие от методов find() и find(int) , оба из которых найдут вхождение шаблона в любом месте строки .

Если мы изменим строку на четырехзначное число “2019” , то matches() вернет true :

@Test
public void whenMatchFourDigitWorks_thenCorrect() {
    Pattern stringPattern = Pattern.compile("\\d\\d\\d\\d");
    Matcher m = stringPattern.matcher("2019");
    
    assertTrue(m.matches());
    assertEquals(0, m.start());
    assertEquals("2019", m.group());
    assertEquals(4, m.end());
    assertTrue(m.matches());
}

Как показано выше, мы также можем использовать такие методы, как start () , group () и end () , чтобы собрать более подробную информацию о матче. Один интересный момент, который следует отметить, заключается в том, что вызов find() несколько раз может возвращать разные выходные данные после вызова этих методов, как мы видели в нашем первом примере, но matches() всегда будет возвращать одно и то же значение.

5. Заключение

В этой статье мы видели, как find() , find(int) и matches() отличаются друг от друга на практическом примере. Мы также видели, как различные методы , такие как start () , group () и end () , могут помочь нам извлечь более подробную информацию о данном совпадении .

Как всегда, полный исходный код статьи доступен на GitHub .