11
votes

Remplacez toutes les occurrences de la sous-chaîne dans une chaîne - ce qui est plus efficace en Java?

Je connais de deux façons de remplacer toutes les occurrences de la sous-chaîne dans une chaîne.

La manière REGEX (en supposant "Substring-to-Be-remplacée" n'incluent pas les caractères spéciaux) : xxx

la chaîne.replace (): xxx

lequel des deux est plus efficace (et pourquoi) ?

Y a-t-il des méthodes plus efficaces que celles décrites ci-dessus?


7 commentaires

Que voulez-vous dire par efficacité? Moins de drain de mémoire? Moins de temps de processeur?


Considérant que regex fonctionnerait à sous-chaîne-to-être-remplacé + , qui permet uniquement de multiples d s à la fin, ils ne font pas ' t même faire n'importe où près de la même chose.


@Vladimir Ivanov plus vite.


@Regex recrue. Alors "moins de temps de processeur"?


@Michael Kjörling Vous posez une bonne question. Il était une fois "plus rapide" traduit directement sur "Moins de temps de processeur". Est-ce encore le cas?


Bien, intuitivement, "plus rapide" se traduit par "avec tout le reste identique, moins mur-horloge". Même matériel, mêmes données d'entrée, etc. qui sembleraient impliquer moins de temps de processeur. Bien sûr, tout le reste n'est jamais identique ...


Je suggère humblement que la seconde est souvent beaucoup plus efficace que la première, car elle prend beaucoup moins de temps d'horloge pour écrire, et moins à lire, à comprendre et à entretenir.


5 Réponses :


15
votes

string.replace () utilise regex en dessous. xxx

Y a-t-il des méthodes plus efficaces que celles ci-dessus décrites deux?

Il est donné que vous opérez sur une mise en œuvre, par exemple, par une matrice, plutôt que par une classe de chaîne immuable (puisque string.replace crée une nouvelle nouvelle String sur chaque invocation). Voir par exemple stringbuilder.replace () .

Compiler une regex subit assez beaucoup de frais généraux qui est clair lors de l'observation du code source . Heureusement, Apache propose une approche alternative dans Stringutils.replace () qui selon le code source (ligne n ° 3732) est assez efficace.


10 commentaires

La mise en œuvre de la chaîne que vous indiquez sur Utilise un modèle pour la méthode de remplacement en question.


@Johan sjöberg stringbuilder.replace () n'est pas la même chose que String.replace () parce qu'il accepte les index de début et de fin au lieu de "String-to-Sta-Substitue".


@Regex recrue, précisément, cela fait partie de ce qui le rend plus efficace


@ Johan Sjöberg mais j'aime la magie (commodité) de simplement cibler la chaîne à remplacer. :) en utilisant stringbuilder.replace () me forcera à utiliser l'approche regex (qui est utilisé quand même, car @jeremy Heiler a souligné).


@Regex recrue, l'avis est bon. Ne cherchez pas à optimiser sauf si dûment justifié. Aussi, voir ma mise à jour pour une excellente alternative.


@ Johan Sjöberg Wow. Merci pour l'impressionnant peaufinage de votre réponse. Ceci est remarquable et très éduqué.


@Johan, stringbuilder.reaplce n'est pas efficace. Cela implique une copie partielle du contenu (en particulier si vous remplacez au début, ce n'est pas bon). Si vous souhaitez une efficacité, vous devez construire la chaîne à partir d'aller, soit via StressBuilder (mais pas de remplacement / insert) ou de caractères simples [].


@Bestssss, comparé à la compilation d'une regex, il ne semble pas nécessairement ce terrible


@Johan, je sais très bien comment cela est mis en œuvre. Avec relèvypely Long Stringbuffer, le remplacement du début sera moins efficace que la Regexp. Si vous voyez ma réponse, je suis toujours assez désemparé, pourquoi Sun est allé Regexp route pour remplacer. Il faut comme 15 à 20 lignes de code pour mettre en œuvre une fonction appropriée. En partie Stringbuffer a perdu son charme en Java1.5 puisqu'il copie toujours le caractère [] (mais au moins ne gaspille plus la mémoire). Ajout également StringBuilder était une idée relativement relativement stupide au lieu de s'appuyer sur la JVM et l'analyse de l'évasion simpliste.


Apache stringutils.replace est un bon crier, beaucoup plus rapide que string.replace ()



1
votes

au lieu d'utiliser String S, qui sont immuables, utilisez des tableaux char ou un autre type mutable (tel que stringbuffer ou stringbuilder ).


3 commentaires

Merci pour ce conseil. Pouvez-vous élaborer plus sur cela? Je sais que les originaux ne sont pas modifiés lors de l'utilisation de remplacer (). Pouvez vous donner un exemple?


Essayez d'utiliser un Stringbuffer .


Un stringbuilder serait plus approprié dans des situations non simultanées.



0
votes

Ne devriez-vous pas comparer le remplacement 2 fois? Cependant, pour une seule invocation, il sera à peine mesurable. Et ferez-vous des millions de comparaisons?

Alors, je m'attendrais à ce que "compiler" soit plus rapide, mais seulement, si vous n'utilisez pas une chaîne constante sans aucune règle de modèle.

Où est le problème d'écrire un micro de référence? Ou recherchez la source.


0 commentaires

1
votes

n'ayant pas fait de profilage ou d'analyse comparative, je dirais que c'est un pari assez sûr que si vous n'avez pas besoin de la magie de regex, alors les frais généraux de l'analyseur d'expression régulier (que vous obtiendrez peu importe ce que de la mémoire ainsi que l'utilisation de la CPU) coûte beaucoup plus que vous ne pouvez gagner à l'autre extrémité.


0 commentaires

2
votes

Voici le Code source de OpenJDK:

public String replace(CharSequence target, CharSequence replacement) {
    return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
       this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
}


1 commentaires

Par conséquent, il s'avère, si l'on doit remplacer la même chaîne, il sera préférable d'être remplacé par remplacement à l'aide d'une regex précompilée.