Differenza tra match () e find () in Java Regex


250

Sto cercando di capire la differenza tra matches()e find().

Secondo Javadoc, (da quello che ho capito), matches()cercherà l'intera stringa anche se trova quello che sta cercando, e find()si fermerà quando trova quello che sta cercando.

Se tale presupposto è corretto, non posso vedere ogni volta che vorresti usare matches()invece di find(), a meno che tu non voglia contare il numero di corrispondenze che trova.

A mio avviso, la classe String dovrebbe quindi avere find()invece matches()come metodo integrato.

Quindi per riassumere:

  1. La mia ipotesi è corretta?
  2. Quando è utile usare matches()invece di find()?

2
Tenere presente che chiamare find()più volte può restituire risultati diversi per lo stesso Matcher. Vedi la mia risposta qui sotto.
L. Holanda,

Risposte:


300

matchesprova a far corrispondere l'espressione all'intera stringa e aggiunge implicitamente ^a all'inizio e $alla fine del modello, il che significa che non cercherà una sottostringa. Da qui l'output di questo codice:

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è una sottostringa di a123bcosì il find()metodo restituisce true. matches()solo "vede" a123bche non è lo stesso di 123e quindi genera false.


25
Questa risposta è fuorviante. matchers()non è semplicemente un find()con implicito circostante ^ e $. Tieni presente che chiamare .find()più di una volta può avere risultati diversi se non preceduto da reset(), mentre matches()restituirà sempre lo stesso risultato. Vedi la mia risposta qui sotto.
L. Holanda,

80

matchesrestituisce vero se l'intera stringa corrisponde al modello dato. findprova a trovare una sottostringa che corrisponda al modello.


35
Si potrebbe dire che matches(p)è lo stesso di quello find("^" + p + "$")che è più chiaro.
jensgram,

4
Solo un esempio per chiarire la risposta: "[az] +" con la stringa "123abc123" non riuscirà a utilizzare match () ma riuscirà a trovare find ().
Bezmax,

3
@Max Esatto, "123abc123".matches("[a-z]+")fallirà proprio come "123abc123".find("^[a-z]+$")farebbe. Il mio punto era che matches()vale per una partita completa, proprio come find()con le ancore di inizio e fine.
jensgram,

5
Pattern.compile("some pattern").matcher(str).matches()è uguale aPattern.compile("^some pattern$").matcher(str).find()
AlexR il

3
@AlexR / @jensgram: non...("some pattern").matcher(str).matches() è esattamente uguale a quello vero solo nella prima chiamata. Vedi la mia risposta qui sotto. ...("^some pattern$").matcher(str).find()
L. Holanda,

62

matches()restituirà vero solo se la stringa completa è abbinata. find()proverà a trovare la ricorrenza successiva all'interno della sottostringa che corrisponde alla regex. Nota l'enfasi sul "prossimo". Ciò significa che il risultato della chiamata find()più volte potrebbe non essere lo stesso. Inoltre, utilizzando find()è possibile chiamare start()per restituire la posizione in cui è stata trovata la sottostringa.

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

Uscita:

Trovato: falso
Trovato: vero - posizione 4
Trovato: vero - posizione 17
Trovato: vero - posizione 20
Trovato: falso
Trovato: falso
Abbinato: falso
-----------
Trovato: vero - posizione 0
Trovato: falso
Trovato: falso
Abbinato: vero
Abbinato: vero
Abbinato: vero
Abbinato: vero

Quindi, fai attenzione quando chiami find()più volte se l' Matcheroggetto non è stato ripristinato, anche quando il regex è circondato ^e $per abbinare l'intera stringa.


2
compagno molto utile
DockYard

6

find()considererà la sottostringa rispetto all'espressione regolare dove as matches()considererà l'espressione completa.

find() restituirà true solo se la sottostringa dell'espressione corrisponde al modello.

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
        }
    }

3

matches();non bufferizza, ma find()buffer. find()cerca prima la fine della stringa, indicizza il risultato e restituisce il valore booleano e l'indice corrispondente.

Ecco perché quando hai un codice simile

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

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

3:int count = 0;

4:while(matcher.find()){

5:count++: }

A 4: Il motore regex che utilizza la struttura del modello leggerà l'intero codice (da indice a indice come specificato da regex[single character]per trovare almeno una corrispondenza. Se tale corrispondenza viene trovata, verrà indicizzata quindi il ciclo verrà eseguito in base a il risultato indicizzato altrimenti se non avesse fatto un calcolo in anticipo come quello matches(), no. L'istruzione while non verrebbe mai eseguita poiché il primo carattere della stringa corrispondente non è un alfabeto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.