3 votes

Classe Java Matcher pour implémenter toFindResult()

Selon le cette question il y a une grande différence entre find y matches() mais tous deux fournissent des résultats sous une forme ou une autre.

Comme une sorte d'utilité, le toMatchResult revient avec les résultats actuels de la fonction matches() opération. J'espère que mon hypothèse sous (1) est valide. (la regex est aquí )

        String line = "aabaaabaaabaaaaaab";
        String regex = "(a*b)a{3}";
        Matcher matcher = Pattern.compile(regex).matcher(line);
        matcher.find();
//        matcher.matches();(1) --> returns false because the regex doesn't match the whole string
        String expectingAab = matcher.group(1);
        System.out.println("actually: " + expectingAab);

Malheureusement, la méthode suivante ne fonctionne pas du tout ("Exception : aucune correspondance trouvée") :

        String line = "aabaaabaaabaaaaaab";
        String regex = "(a*b)a{3}";
        String expectingAab = Pattern.compile(regex).matcher(line).toMatchResult().group(1);
        System.out.println("actually: " + expectingAab);

Comment cela se fait-il ? Ma première hypothèse était que cela ne fonctionne pas parce que la regex doit correspondre à la chaîne entière ; mais la même exception est levée avec la valeur de la chaîne. aabaaa également...

Bien entendu, l'outil de sélection doit être placé dans l'état correct à l'aide de la fonction find() Mais qu'en est-il si je souhaite utiliser un oneliner ? J'ai en fait implémenté un appel d'utilité pour cela :

protected static class FindResult{
    private final Matcher innerMatcher;
    public FindResult(Matcher matcher){
        innerMatcher = matcher;
        innerMatcher.find();
    }
    public Matcher toFindResult(){
        return  innerMatcher;
    }
}

public static void main(String[] args){
    String line = "aabaaabaaabaaaaaab";
    String regex = "(a*b)a{3}";
    String expectingAab = new FindResult(Pattern.compile(regex).matcher(line)).toFindResult().group(1);
    System.out.println("actually: " + expectingAab);
}

Je sais pertinemment que ce n'est pas une solution optimale pour créer un oneliner, notamment parce qu'elle fait peser de lourdes charges sur le garbage collector .

Existe-t-il une solution plus simple et plus efficace ?

Il est à noter que je cherche une solution java8. La logique de correspondance fonctionne différemment au-dessus de java 9.

3voto

Sweeper Points 1267

La méthode n'a pas besoin de champs d'instance pour fonctionner. Il peut s'agir d'une aide statique :

class MatcherUtils {
  public static MatchResult findResult(Matcher matcher) {
    matcher.find();
    return matcher.toMatchResult();
  }
}

Utilisation :

MatchResult result = MatcherUtils.findResult(Pattern.compile("...").matcher("..."));

Notez que vous pourriez vouloir gérer le cas où find ne trouve rien (merci pour le clin d'œil), Holger !) :

class MatcherUtils {
  public static Optional<MatchResult> findResult(Matcher matcher) {
    return Optional.of(matcher)
             .filter(Matcher::find)
             .map(Matcher::toMatchResult);
    /*
    if (matcher.find()) {
      return Optional.of(matcher.toMatchResult());
    } else {
      return Optional.empty();
    }
    */
  }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X