Разница между match() и find() в Java Regex
Я пытаюсь понять разницу между matches()
и find()
.
Согласно Javadoc, (из того, что я понимаю), matches()
будет искать всю строку, даже если она найдет то, что она ищет, и find()
остановится, когда найдет то, что она ищет.
Если это предположение верно, я не могу видеть, когда вы хотите использовать matches()
вместо find()
, если вы не хотите подсчитать количество совпадений, которое оно находит.
По-моему, класс String должен иметь find()
вместо matches()
как встроенный метод.
Итак, суммируем:
- Правильно ли мое предположение?
- Когда полезно использовать
matches()
вместо find()
?
Ответы
Ответ 1
matches
пытается сопоставить выражение со всей строкой и неявно добавить ^
в начале и $
в конце вашего шаблона, то есть он не будет искать подстроку. Отсюда вывод этого кода:
public static void main(String[] args) throws ParseException {
Pattern p = Pattern.compile("\\d\\d\\d");
Matcher m = p.matcher("a123b");
System.out.println(m.find());
System.out.println(m.matches());
p = Pattern.compile("^\\d\\d\\d$");
m = p.matcher("123");
System.out.println(m.find());
System.out.println(m.matches());
}
/* output:
true
false
true
true
*/
123
является подстрокой a123b
, поэтому метод find()
выводит значение true. matches()
только "видит" a123b
, который не совпадает с 123
и, следовательно, выводит false.
Ответ 2
matches
возвращает true, если вся строка соответствует заданному шаблону. find
пытается найти подстроку, которая соответствует шаблону.
Ответ 3
matches()
возвращает только true, если полная строка соответствует.
find()
попытается найти следующее событие в подстроке, которое соответствует регулярному выражению. Обратите внимание на акцент на "следующий". Это означает, что результат вызова find()
несколько раз может быть не таким. Кроме того, используя find()
, вы можете вызвать start()
, чтобы вернуть позицию, подстроенную подстрокой.
final Matcher subMatcher = Pattern.compile("\\d+").matcher("skrf35kesruytfkwu4ty7sdfs");
System.out.println("Found: " + subMatcher.matches());
System.out.println("Found: " + subMatcher.find() + " - position " + subMatcher.start());
System.out.println("Found: " + subMatcher.find() + " - position " + subMatcher.start());
System.out.println("Found: " + subMatcher.find() + " - position " + subMatcher.start());
System.out.println("Found: " + subMatcher.find());
System.out.println("Found: " + subMatcher.find());
System.out.println("Matched: " + subMatcher.matches());
System.out.println("-----------");
final Matcher fullMatcher = Pattern.compile("^\\w+$").matcher("skrf35kesruytfkwu4ty7sdfs");
System.out.println("Found: " + fullMatcher.find() + " - position " + fullMatcher.start());
System.out.println("Found: " + fullMatcher.find());
System.out.println("Found: " + fullMatcher.find());
System.out.println("Matched: " + fullMatcher.matches());
System.out.println("Matched: " + fullMatcher.matches());
System.out.println("Matched: " + fullMatcher.matches());
System.out.println("Matched: " + fullMatcher.matches());
Будет выводиться:
Found: false
Found: true - position 4
Found: true - position 17
Found: true - position 20
Found: false
Found: false
Matched: false
-----------
Found: true - position 0
Found: false
Found: false
Matched: true
Matched: true
Matched: true
Matched: true
Итак, будьте осторожны при вызове find()
несколько раз, если объект Matcher
не был reset, даже если регулярное выражение окружено ^
и $
для соответствия полной строке.
Ответ 4
matches();
не буферизует, а find()
- буферы. find()
сначала выполняет поиск в конце строки, индексирует результат и возвращает логическое значение и соответствующий индекс.
Вот почему, когда у вас есть код типа
1:Pattern.compile("[a-z]");
2:Pattern.matcher("0a1b1c3d4");
3:int count = 0;
4:while(matcher.find()){
5:count++: }
В 4: Механизм регулярных выражений, использующий структуру шаблонов, будет читать весь ваш код (индекс индексируется, как указано regex[single character]
, чтобы найти хотя бы одно совпадение. найденный, он будет проиндексирован, тогда цикл будет выполняться на основе индексированного результата else, если он не выполнил вычисления, например, что matches()
; не делает. Оператор while никогда не будет выполняться, поскольку первый символ совпадающей строки не является алфавит.
Ответ 5
find()
рассмотрит подстроку относительно регулярного выражения, где matches()
рассмотрит полное выражение.
find()
возвращает true, только если подстрока выражения совпадает с шаблоном.
public static void main(String[] args) {
Pattern p = Pattern.compile("\\d");
String candidate = "Java123";
Matcher m = p.matcher(candidate);
if (m != null){
System.out.println(m.find());//true
System.out.println(m.matches());//false
}
}