2009-11-16 6 views
2

Ci-dessous exemple de texte:Comment obtenir une bonne perfomance de Regex en java

String id = "A:abc,X:def,F:xyz,A:jkl"; 

est Ci-dessous regex:

Pattern p = Pattern.compile("(.*,)?[AC]:[^:]+$"); 
if(p.matcher(id).matches()) { 
    System.out.println("Hello world!") 
} 

Lorsqu'il est exécuté code ci-dessus devrait imprimer Bonjour tout le monde !.

Cette regex peut-elle être modifiée pour améliorer les performances?

+1

Il serait préférable que vous décriviez ce que vous voulez faire correspondre. Voulez-vous faire correspondre une séquence comme votre exemple, où le dernier élément est «A: quelque chose» ou «C: quelque chose»? – Blixt

+0

Dans l'exemple ci-dessus je veux faire correspondre le dernier jeton qui est A: jkl – Jaydeep

Répondre

8

Comme je ne peux pas voir votre code entier, je peux seulement supposer que vous faites la compilation de modèle dans votre boucle/méthode/etc. Une chose qui peut améliorer les performances est de compiler au niveau de la classe et de ne pas recompiler le motif à chaque fois. A part ça, je ne vois pas grand-chose d'autre que vous pourriez changer.

+0

Pattern.compile était à l'intérieur de la boucle et j'ai déménagé, Mais je vérifie s'il y a une chance d'améliorer regex. – Jaydeep

3
Pattern p = Pattern.compile(".*[AC]:[^:]+$"); 
if(p.matcher(id).matches()) { 
    System.out.println("Hello world!") 
} 

Comme vous semblez être intéressé que si elle la chaîne se termine par A ou C suivi par deux points et quelques caractères qui ne sont pas vous pouvez simplement côlons utiliser .* au lieu de (.*,)? (ou faire vous voulez vraiment saisir les choses avant le dernier morceau?)

Si les choses après les deux points est minuscules, vous pouvez même faire

Pattern p = Pattern.compile(".*[AC]:[a-z]+$"); 

Et si vous voulez faire correspondre cela plusieurs fois de suite (par ex. loop) assurez-vous de compiler le motif en dehors de la boucle.

e, g

Pattern p = Pattern.compile(".*[AC]:[a-z]+$"); 
Matcher m = p.matcher(id); 
while(....) { 
    ... 
    // m.matches() 
    ... 
    // prepare for next loop m.reset(newvaluetocheck); 
} 
+0

Ouais c'est plus comme ce que j'utiliserais. Si la partie avant les deux-points peut contenir plus d'un caractère, vous devez probablement ajouter une limite de mot. Ou un look-behind qui vérifie le début de la chaîne/virgule. – Blixt

+0

Une raison pour quitter la vérification de la virgule est d'éviter de trouver quelque chose comme NA: jkl à la fin de la chaîne. – PSpeed

1

Déplacer Pattern instanciation à un champ statique final (erm, constante), dans votre code actuel pour recompiler essentiellement le même Pattern chaque fois (non, Pattern doesn ne cache rien!). Cela devrait vous donner un coup de pouce perceptible dès le départ.

0

Avez-vous même besoin d'utiliser des expressions regualr? Il semble qu'il n'y ait pas une grande variété dans ce que vous testez. Si vous avez besoin d'utiliser la regex comme vous l'avez dit, il ne sert à rien de la compiler une seule fois. Si vous avez seulement besoin de vérifier le dernier jeton, vous pouvez peut-être simplifier l'expression régulière: [AC]:[^:]{3}$.

Pourriez-vous éventuellement utiliser quelque chose le long de ces lignes (non testé ...)?

private boolean isId(String id) 
    { 
     char[] chars = id.toCharArray(); 
     boolean valid = false; 
     int length = chars.length; 

     if (length >= 5 && chars[length - 4] == ':') 
     { 
      char fifthToLast = chars[length - 5]; 

      if (fifthToLast == 'A' || fifthToLast == 'C') 
      { 
       valid = true; 

       for (int i = length - 1; i >= length - 4; i--) 
       { 
        if (chars[i] == ':') 
        { 
         valid = false; 
         break; 
        } 
       } 
      } 
     } 

     return valid; 
    } 
Questions connexes