Diferença entre correspondências () e find () no Java Regex

250

Estou tentando entender a diferença entre matches()e find().

De acordo com o Javadoc, (pelo que entendi), matches()procurará a string inteira, mesmo que encontre o que está procurando, e find()parará quando encontrar o que está procurando.

Se essa suposição estiver correta, não consigo ver sempre que você deseja usar em matches()vez de find(), a menos que queira contar o número de correspondências encontradas.

Na minha opinião, a classe String deve ter, em find()vez de matches()um método embutido.

Então, para resumir:

  1. Minha suposição está correta?
  2. Quando é útil usar em matches()vez de find()?
Shervin Asgari
fonte
2
Lembre-se de que ligar find()várias vezes pode retornar resultados diferentes para o mesmo Matcher. Veja minha resposta abaixo.
23413 Holanda

Respostas:

300

matchestenta combinar a expressão com toda a cadeia e adicionar implicitamente um ^no início e $no final do seu padrão, o que significa que ele não procurará uma substring. Daí a saída deste código:

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é uma substring de, a123bportanto, o find()método gera true. matches()apenas 'vê' a123bque não é o mesmo que 123e, portanto, gera falso.

Sanjay T. Sharma
fonte
25
Esta resposta é enganosa. matchers()não é simplesmente um find()com implicado ^ e $. Lembre-se de que ligar .find()mais de uma vez pode ter resultados diferentes se não for precedido por reset(), enquanto matches()sempre retornará o mesmo resultado. Veja minha resposta abaixo.
21415 Holanda
80

matchesreturn true se a string inteira corresponder ao padrão especificado. findtenta encontrar uma substring que corresponda ao padrão.

khachik
fonte
35
Você poderia dizer que matches(p)é o mesmo como find("^" + p + "$")se isso fosse mais claro.
Jsgram # dez15
4
Apenas um exemplo para esclarecer a resposta: "[az] +" com a string "123abc123" falhará usando correspondências (), mas será bem-sucedido usando find ().
Bezmax
3
@ Max Exatamente, "123abc123".matches("[a-z]+")falhará exatamente como "123abc123".find("^[a-z]+$")faria. Meu argumento foi que isso matches()vale para uma partida completa, assim como find()nas âncoras de início e de fim.
Jsgram # dez15
5
Pattern.compile("some pattern").matcher(str).matches()é igual aPattern.compile("^some pattern$").matcher(str).find()
AlexR 15/12
3
@AlexR / @jensgram: não...("some pattern").matcher(str).matches() é exatamente igual ao que é verdadeiro apenas na primeira chamada. Veja minha resposta abaixo. ...("^some pattern$").matcher(str).find()
L. Holanda
62

matches()retornará true somente se a string completa for correspondida. find()tentará encontrar a próxima ocorrência dentro da substring que corresponde ao regex. Observe a ênfase no "próximo". Isso significa que o resultado da chamada find()várias vezes pode não ser o mesmo. Além disso, usando find()você pode chamar start()para retornar a posição em que a substring foi correspondida.

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());

Saída:

Encontrado: false
Encontrado: verdadeiro - posição 4
Encontrado: verdadeiro - posição 17
Encontrado: verdadeiro - posição 20
Encontrado: false
Encontrado: false
Correspondido: falso
-----------
Encontrado: verdadeiro - posição 0
Encontrado: false
Encontrado: false
Correspondido: verdadeiro
Correspondido: verdadeiro
Correspondido: verdadeiro
Correspondido: verdadeiro

Portanto, tenha cuidado ao chamar find()várias vezes se o Matcherobjeto não tiver sido redefinido, mesmo quando o regex estiver cercado ^e $corresponder à seqüência completa.

L. Holanda
fonte
2
companheiro muito útil
Dockyard
6

find()considerará a sub-string contra a expressão regular, onde as matches()considerará a expressão completa.

find() retornará true somente se a sub-string da expressão corresponder ao padrão.

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
        }
    }
Sumanth Varada
fonte
3

matches();não faz buffer, mas find()buffers. find()procura no final da string primeiro, indexa o resultado e retorna o valor booleano e o índice correspondente.

É por isso que quando você tem um código como

1:Pattern.compile("[a-z]");

2:Pattern.matcher("0a1b1c3d4");

3:int count = 0;

4:while(matcher.find()){

5:count++: }

Em 4: o mecanismo regex usando a estrutura padrão lerá todo o seu código (indexe para indexar conforme especificado por regex[single character]para encontrar pelo menos uma correspondência. Se essa correspondência for encontrada, ela será indexada, o loop será executado com base em o resultado indexado, caso contrário, se não fizesse o cálculo antecipado, como o que matches()não faz. A instrução while nunca seria executada, pois o primeiro caractere da sequência correspondente não é um alfabeto.


fonte