IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

optimisez vos regex

Cet article vise à vous permettre une utilisation plus efficace des expressions régulières en java

Article lu   fois.

L'auteur

Profil ProSite personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

Introduction

Les expressions régulières ou regex sont de formidables outils de travail très utiles à tous les développeurs et ceci non seulement dans le monde java. Dans cet article, nous allons découvrir comment l'utilisation judicieuse des regex permet l'optimisation d'un code java.

I. Problématique

Nous allons illustrer la puissance des regex via un exemple très simple. Il s'agit de lire un fichier ligne par ligne et de diviser chaque ligne en un ensemble de segments séparés par un espace. Par exemple, la division de la ligne suivante donne : Exemple
Ceci est un ligne
Résultat
Ceci,est,une,ligne

II. Première tentative

La premier réflexe qu'un développeur, confronté à ce problème, peut avoir est de faire appel à la méthode split de la classe String:

 
Sélectionnez
1.
2.
3.
4.
5.
6.
BufferedReader br;
String line;
br = new BufferedReader(new FileReader(file));
while((line=br.readLine()) != null){
		line.split("//s+");			
}

L'exécution de ce code sur un fichier texte de quelques mégas octets est de 2284 ms.

III. Première Optimisation

Voici le code source de la méthode split() de la classe String :

 
Sélectionnez
Pattern.compile(regex).split(this,0);

Ainsi, le pattern est compilé à chaque nouvelle ligne. Si on compile le Pattern une seule fois, nous obtiendrons sûrement de meilleures performances:

 
Sélectionnez
private static final Pattern SEPARATOR_PATTERN = Pattern.compile("//s+");
		
// le reste ne change pas
SEPARATOR_PATTERN.split(line);

Cette première modification améliore le temps d'exécution qui passe à 1849 ms.

IV. Deuxième Optimisation

Comment améliorer encore ce code? L'analyse du code source de la méthode split() de la classe Pattern a permis d'exprimer quelques critiques à son égard:

  • certains détails de la méthodes sont superflus pour ce cas et peuvent être éliminés
  • une nouvelle classe Matcher est créée à chaque appel de la méthode ce qui peut être évité

Voici le nouveau code "aménagé" de la méthode split()

 
Sélectionnez
private Matcher matcher = null;
 
public String[] splitUsingMatcherOptimized(String str){	
    //éviter la création à chaque fois d'un nouveau Matcher
    //via une lazy initialisation et l'utilisation de la 
    //méthode reset()
    if (matcher == null) {
        matcher = SEPARATOR_PATTERN.matcher(str);			
    } else {
        matcher.reset(str);
    }

    int index = 0;
    ArrayList<String> matchList = new ArrayList<String>();
     
     // ajoute les segments avant chaque correspondance trouvée
    while(matcher.find()) {
           String match = str.substring(index, matcher.start());
           matchList.add(match);
           index = matcher.end();
    }
     
    // si aucune correspondance n' a été trouvée on renvoie 
    // le str original dans un tableau
    if (index == 0)
          return new String[]{str};
     
    // ajoute le dernier segment
    String lastMatch = str.substring(index, str.length());
    matchList.add(lastMatch);
     
    // Construit le résultat
    return (String[]) matchList.toArray(new String[matchList.size()]);
}

En utilisant cette nouvelle méthode, le code s'exécute maintenant en 1511 ms.

Conclusion

Les performances du code ont été améliorée grâce à une utilisation plus efficace des regex (un gain non négligeable de 773 ms).Nous pouvons ainsi déduire quelques règles simples concernant les regex:

  • Préférer la méthode split de Pattern à celle de String
  • Compiler le Pattern une seule fois lorsque la même regex sera utilisée plusieurs fois
  • Réutiliser le même Matcher via la méthode reset plutôt que d'en créer un à chaque fois

Liens

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

Ce document est issu de http://www.developpez.com et reste la propriété exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.