2 votes

Performance de String.replaceFirst par rapport au remplacement algorithmique

Supposons que je veuille remplacer la première occurrence de "yyy" dans une chaîne par "zzz". String.replaceFirst semble être une solution parfaite.

str = str.repaceFirst("yyy", "zzz");

Mais y a-t-il un problème de performance ? La solution suivante fait-elle une différence au niveau des performances ?

int i = s.indexOf("yyy");
if (i != -1) {
    str = str.substring(0, i) + "zzz" + s.substring(i + 3);
}

4voto

nhahtdh Points 28167

J'ai écrit un peu de code pour tester les performances. Veuillez l'exécuter sur votre boîte avec le paramètre approprié pour le tester. La ligne de commande accepte un double de 0 à 1 qui représente le rapport entre les entrées de test et l'insertion. "yyy" sous-chaîne.

Méthodologie

5000 chaîne aléatoire de longueur 50, 100, 500, 1000, etc. sont générés. Un certain pourcentage des 5000 chaînes de caractères sont insérées avec la séquence "yyy". à une position aléatoire . (En raison de la méthode de génération, les chaînes de caractères ne contiendront qu'une seule instance de "yyy" s'il y en a, mais je ne pense pas que ce soit un problème). Pour chaque combinaison de (longueur des chaînes) et (approches), je lance le test 30 fois et prenez la moyenne.

Les 3 approches ci-dessous sont testées :

  1. replaceFirst :

    public static String replaceFirstApproach(String input) {
        return input.replaceFirst("yyy", "zzz");
    }
  2. substring :

    public static String substringApproach(String input) {
        int i = input.indexOf("yyy");
    
        if (i != -1) {
            input = input.substring(0, i) + "zzz" + input.substring(i + 3);
        }
    
        return input;
    }
  3. Utilisez StringBuilder pour construire la chaîne de sortie :

    public static String appendStringBuilder(String input) {
        int i = input.indexOf("yyy");
    
        if (i != -1) {
            StringBuilder output = new StringBuilder(input.length());
            output.append(input, 0, i).append("zzz").append(input, i + 3, input.length());
            return output.toString();
        } else {
            return input;
        }
    }

Résultat

Le programme est exécuté sur JVM 7, Windows 7. Les chiffres sont le temps moyen pour traiter 1 lot de 5000 chaînes aléatoires en microsecondes .

Sur 0% d'insérer la sous-chaîne "yyy"

       Length |      50        100        500        1000         5000
--------------|-------------------------------------------------------
 replaceFirst |   17389      22718      74194      137285       629438
    substring |    4429       7246      13421       18069        78920
StringBuilder |    4604       5615      11509       19093        79366

Sur 25% d'insérer la sous-chaîne "yyy"

       Length |      50        100        500        1000         5000
--------------|-------------------------------------------------------
 replaceFirst |   18531      24959      78211      146956       692992
    substring |    5250       6764      18994       27959       113805
StringBuilder |    5768       8609      23857       45789       205580

Sur 50% d'insérer la sous-chaîne "yyy"

       Length |      50        100        500        1000         5000
--------------|-------------------------------------------------------
 replaceFirst |   19833      27648      90932      162558       760558
    substring |    6007       8848      21909       37415       154959
StringBuilder |    7075      12095      37765       70038       327171

Sur 75% d'insérer la sous-chaîne "yyy"

       Length |      50        100        500        1000         5000
--------------|-------------------------------------------------------
 replaceFirst |   20318      28387      95967      176051       845799
    substring |    6840       9940      27469       47218       198464
StringBuilder |    8794      13272      50498       94644       470656

Sur 100% d'insérer la sous-chaîne "yyy"

       Length |      50        100        500        1000         5000
--------------|-------------------------------------------------------
 replaceFirst |   22984      31302     103640      192179       892965
    substring |    7846      11494      37093       58544       258356
StringBuilder |   11113      24499      66164      121784       592664

Conclusion

L'approche avec replaceFirst est toujours le plus lent. Lorsque "yyy" n'est pas trouvée, elle est 3 à 10 fois plus lente que les 2 autres approches. Lorsque "yyy" peut être trouvée, elle est toujours plus lente que la fonction substring par 3 fois, et StringBuilder par 1,5 fois.

L'approche consistant à concaténer une chaîne de caractères avec + y substring est 2 fois plus rapide que StringBuilder quand "yyy" la sous-chaîne peut être trouvée et la chaîne est longue.

Le cas d'utilisation ici est cependant assez localisé. Et bien que le substring est plus rapide, mais à moins que vous ne fassiez un traitement intensif des chaînes de caractères, le gain est insignifiant.

2voto

Peter Lawrey Points 229686

Souvent, le plus important est d'écrire un code clair et simple. En termes de performances et pour ceux qui doivent maintenir le code, la première option est la meilleure.

Si vous déterminez que cet appel est assez fréquent et que cela signifie que vous prenez trop de temps, alors vous pouvez envisager d'utiliser un codage plus complexe. À moins que vous n'ayez mesuré la différence, je suppose que ce n'est qu'une supposition. Dans ce cas, la deuxième ligne pourrait être une option.

BTW Il existe peut-être des approches plus rapides, comme l'utilisation d'un StringBuilder au lieu de créer une chaîne, selon le contexte.

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