Différence entre matches () et find () dans Java Regex

250

J'essaie de comprendre la différence entre matches()et find().

Selon le Javadoc, (d'après ce que je comprends), matches()cherchera la chaîne entière même s'il trouve ce qu'il cherche, et find()s'arrêtera quand il trouvera ce qu'il cherche.

Si cette hypothèse est correcte, je ne vois pas quand vous voudriez utiliser à la matches()place de find(), à moins que vous ne vouliez compter le nombre de correspondances qu'il trouve.

À mon avis, la classe String devrait alors avoir find()au lieu d' matches()une méthode intégrée.

Donc, pour résumer:

  1. Mon hypothèse est-elle correcte?
  2. Quand est-il utile d'utiliser à la matches()place de find()?
Shervin Asgari
la source
2
Sachez que find()plusieurs appels peuvent renvoyer des résultats différents pour le même Matcher. Voir ma réponse ci-dessous.
L. Holanda

Réponses:

300

matchesessaie de faire correspondre l'expression à la chaîne entière et d'ajouter implicitement un ^au début et $à la fin de votre modèle, ce qui signifie qu'il ne recherchera pas de sous-chaîne. D'où la sortie de ce code:

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
*/

123est une sous-chaîne de a123bsorte que la find()méthode renvoie true. matches()ne «voit» que a123bce qui n'est pas la même chose 123et sort donc faux.

Sanjay T. Sharma
la source
25
Cette réponse est trompeuse. matchers()n'est pas simplement un find()avec entourer implicite ^ et $. Sachez qu'appeler .find()plus d'une fois peut avoir des résultats différents s'il n'est pas précédé reset(), tandis que matches()renvoie toujours le même résultat. Voir ma réponse ci-dessous.
L. Holanda
80

matchesretourne vrai si la chaîne entière correspond au modèle donné. findessaie de trouver une sous-chaîne qui correspond au modèle.

khachik
la source
35
On pourrait dire que matches(p)c'est la même chose que find("^" + p + "$")si c'est plus clair.
jensgram
4
Juste un exemple pour clarifier la réponse: "[az] +" avec la chaîne "123abc123" échouera en utilisant matches () mais réussira en utilisant find ().
bezmax
3
@Max Exactement, "123abc123".matches("[a-z]+")échouera comme le "123abc123".find("^[a-z]+$")ferait. Mon point était, cela matches()vaut pour un match complet, tout comme find()pour les ancres de début et de fin.
jensgram
5
Pattern.compile("some pattern").matcher(str).matches()est égal àPattern.compile("^some pattern$").matcher(str).find()
AlexR
3
@AlexR / @jensgram: ...("some pattern").matcher(str).matches()n'est pas exactement égal à ...("^some pattern$").matcher(str).find()ce qui n'est vrai que lors du premier appel. Voir ma réponse ci-dessous.
L. Holanda
62

matches()ne renverra true que si la chaîne complète correspond. find()va essayer de trouver l' occurrence suivante dans la sous-chaîne qui correspond à l'expression régulière. Notez l'accent mis sur «le prochain». Cela signifie que le résultat de find()plusieurs appels pourrait ne pas être le même. De plus, en utilisant, find()vous pouvez appeler start()pour renvoyer la position à laquelle la sous-chaîne a été mise en correspondance.

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

Sortira:

Trouvé: faux
Trouvé: vrai - position 4
Trouvé: vrai - position 17
Trouvé: vrai - position 20
Trouvé: faux
Trouvé: faux
Correspondant: faux
-----------
Trouvé: vrai - position 0
Trouvé: faux
Trouvé: faux
Correspondant: vrai
Correspondant: vrai
Correspondant: vrai
Correspondant: vrai

Donc, soyez prudent lorsque vous appelez find()plusieurs fois si l' Matcherobjet n'a pas été réinitialisé, même lorsque l'expression régulière est entourée de ^et $pour correspondre à la chaîne complète.

L. Holanda
la source
2
compagnon très utile
DockYard
6

find()considérera la sous-chaîne par rapport à l'expression régulière où as matches()considérera l'expression complète.

find() renvoie true uniquement si la sous-chaîne de l'expression correspond au modèle.

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
la source
3

matches();ne met pas en mémoire tampon, mais les find()tampons. find()recherche d'abord la fin de la chaîne, indexe le résultat et renvoie la valeur booléenne et l'index correspondant.

C'est pourquoi lorsque vous avez un code comme

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

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

3:int count = 0;

4:while(matcher.find()){

5:count++: }

À 4: le moteur d'expression régulière utilisant la structure de modèle lira tout votre code (index à index comme spécifié par le regex[single character]pour trouver au moins une correspondance. Si une telle correspondance est trouvée, elle sera indexée puis la boucle s'exécutera en fonction de le résultat indexé sinon s'il n'a pas fait de calcul anticipé comme lequel matches(); ne le fait pas. L'instruction while ne s'exécuterait jamais car le premier caractère de la chaîne correspondante n'est pas un alphabet.


la source