Aperçu
StringBuilder et StringBuffer sont deux concepts facilement confondus. Cet article part à partir du code source et examine simplement les similitudes et les différences entre les deux.
Il est facile de savoir que l'un de ces deux est en file d'attente, et celui-ci est inefficace.
Description dans Java Doc
Java Doc est une annotation écrite par des personnes qui écrivent du code source. Regardons d'abord Java Doc.
Balein de cordes
Une séquence mutable de caractères. Cette classe fournit une API compatible avec StringBuffer, mais sans garantie de synchronisation. Cette classe est conçue pour être utilisée en remplacement d'allumage pour StringBuffer à des endroits où le tampon de chaîne était utilisé par un seul thread (comme c'est généralement le cas). Dans la mesure du possible, il est recommandé que cette classe soit utilisée en préférence pour StringBuffer, car elle sera plus rapide dans la plupart des implémentations.
Les principales opérations sur un Builder de String sont les méthodes d'ajout et d'insertion, qui sont surchargées de manière à accepter les données de tout type. Chacun convertit efficacement une donnée donnée en une chaîne, puis ajoute ou insère les caractères de cette chaîne au générateur de chaîne. La méthode d'ajout ajoute toujours ces caractères à la fin du constructeur; La méthode d'insert ajoute les caractères à un point spécifié.
Par exemple, si Z fait référence à un objet de générateur de chaînes dont le contenu actuel est "Démarrer", alors l'appel de méthode Z.APPEND ("LE") ferait que le constructeur de chaînes contiendrait "Starking", tandis que Z.Insert (4, "LE") alterait le constructeur de chaînes à contenir "Starlet".
En général, si SB fait référence à une instance d'un stringbuilder, alors sb.append (x) a le même effet que sb.insert (sb.length (), x).
Chaque constructeur de cordes a une capacité. Tant que la longueur de la séquence de caractères contenue dans le générateur de cordes ne dépasse pas la capacité, il n'est pas nécessaire d'allouer un nouveau tampon interne. Si le tampon interne déborde, il est automatiquement agrandi.
Les instances de StringBuilder ne sont pas sûres pour une utilisation par plusieurs threads. Si une telle synchronisation est requise, il est recommandé d'utiliser java.lang.stringbuffer.
Sauf indication contraire, passer un argument nul à un constructeur ou une méthode de cette classe entraînera un lancement d'une nulpointerException.
Depuis:
1.5
Auteur:
Michael McCloskey
Voir aussi:
java.lang.stringbuffer
java.lang.string
Stringbuffer
Une séquence de caractères mutable et sûre. Un tampon de chaîne est comme une chaîne, mais peut être modifié. À tout moment, il contient une séquence particulière de caractères, mais la longueur et le contenu de la séquence peuvent être modifiés via certains appels de méthode.
Les tampons de chaîne sont sûrs à utiliser par plusieurs threads. Les méthodes sont synchronisées si nécessaire afin que toutes les opérations sur une instance particulière se comportent comme si elles se produisaient dans un ordre de série conforme à l'ordre des appels de méthode effectués par chacun des threads individuels impliqués.
Les principales opérations sur un STRINGBUFFER sont les méthodes d'ajout et d'insertion, qui sont surchargées afin d'accepter les données de tout type. Chacun convertit efficacement une donnée donnée en une chaîne, puis ajoute ou insère les caractères de cette chaîne dans le tampon de chaîne. La méthode d'ajout ajoute toujours ces caractères à la fin du tampon; La méthode d'insert ajoute les caractères à un point spécifié.
Par exemple, si Z fait référence à un objet de tampon de chaîne dont le contenu actuel est "Démarrer", alors l'appel de méthode z.append ("le") ferait contenir le tampon de chaîne "Comasure", tandis que z.insert (4, "le") alterait le tampon de chaîne à contenir "Starlet".
En général, si SB fait référence à une instance d'un stringbuffer, alors sb.append (x) a le même effet que sb.insert (sb.length (),
Chaque fois qu'une opération se produit impliquant une séquence source (comme l'ajout ou l'insertion d'une séquence source), cette classe se synchronise uniquement sur le tampon de chaîne effectuant l'opération, pas sur la source. Notez que même si StringBuffer est conçu pour être sûr à utiliser simultanément à partir de plusieurs threads, si le constructeur ou l'opération d'ajout ou d'insertion est passé une séquence source qui est partagée sur les threads, le code d'appel doit s'assurer que l'opération a une vue cohérente et immuable de la séquence source pendant la durée de l'opération. Cela pourrait être satisfait par l'appelant tenant une serrure pendant l'appel de l'opération, en utilisant une séquence source immuable, ou en ne partageant pas la séquence source à travers les threads.
Chaque tampon de chaîne a une capacité. Tant que la longueur de la séquence de caractères contenue dans le tampon de chaîne ne dépasse pas la capacité, il n'est pas nécessaire d'allouer un nouveau tableau de tampon interne. Si le tampon interne déborde, il est automatiquement agrandi.
Sauf indication contraire, passer un argument nul à un constructeur ou une méthode de cette classe entraînera un lancement d'une nulpointerException.
À partir de la version JDK 5, cette classe a été complétée par une classe équivalente conçue pour une utilisation par un seul thread, StringBuilder. La classe StringBuilder doit généralement être utilisée en préférence à celle-ci, car elle prend en charge toutes les mêmes opérations, mais elle est plus rapide, car elle ne fait aucune synchronisation.
Depuis:
JDK1.0
Auteur:
Arthur van Hoff
Voir aussi:
java.lang.stringbuilder
java.lang.string
Résumé de Javadoc
D'après ce qui précède, nous pouvons voir:
StringBuffer et StringBuilder peuvent être considérés comme des chaînes variables.
StringBuffer est thread-safe et apparaît en premier, et il est disponible dans JDK1.0.
StringBuilder est sans thread-safe et apparaît plus tard et n'existe que dans JDK1.5.
Les interfaces des deux sont exactement les mêmes, et StringBuilder est plus rapide.
En fait, il est bon de l'utiliser normalement, connaissez ces points, mais je veux toujours voir comment il est implémenté dans le code source.
Code source
Comment réaliser la sécurité des fils
Vous pouvez voir à partir du code source qui hérite à la fois une classe abstraite abstraitsstringBuilder
Classe finale publique StringBuffer étend AbstractStringBuilder implémente Java.io.Serializable, CharSequencePublic final classe StringBuilder étend AbstractStringBuilder implémente Java.io.Serializable, CharSedence
La quantité de code n'est pas très grande, StringBuilder440 lignes de code, StringBuffer718 lignes de code, et le plus est AbstractStringBuilder, avec un total de 1440 lignes de code.
De plusieurs angles, nous regardons le code, l'un est à quoi ressemblent certaines structures internes clés, et l'autre est la façon dont les fonctions que nous utilisons couramment sont implémentées. Parce que la corde est immuable, elle est placée dans une piscine constante. Il est deviné que StringBuilder et StringBuffer doivent être implémentés à l'aide d'un tableau char.
/ ** * La valeur est utilisée pour le stockage des caractères. * / char [] valeur; / ** * Le nombre est le nombre de caractères utilisés. * / int count;
On peut voir que les données sont stockées avec la valeur et que la longueur est représentée par un décompte.
Voyons les différentes implémentations de plusieurs méthodes courantes.
Stringbuffer
@Override public synchronisé stringbuffer append (string str) {toStringCache = null; Super.APPEND (STR); retourner ceci; } / ** * @throws stringIndexOutofBoundSException {@InheritDoc} * / @Override public synchronisé stringbuffer insert (int offset, string str) {toStringCache = null; super.insert (offset, str); retourner ceci; } @Override public synchronisé chaîne toString () {if (toStringCache == null) {toStringCache = arrays.copyofrange (valeur, 0, count); } return new String (toStringCache, true); }Balein de cordes
@Override public StringBuilder append (string str) {super.append (str); retourner ceci; } / ** * @throws stringIndexoutofBoundSException {@InheritDoc} * / @Override public StringBuilder insert (int offset, string str) {super.insert (offset, str); retourner ceci; } @Override public String toString () {// Créez une copie, ne partagez pas le tableau de retour nouvelle chaîne (valeur, 0, count); }Comme on peut le voir dans le code, dans la plupart des cas, Strinbbuffer ajoute simplement un mot-clé synchronisé pour assurer la sécurité des filetages. Mais la méthode de tostring est différente, donc j'en parlerai plus tard.
Initialiser la taille et comment grandir
Puisqu'il s'agit en fait d'un tableau, la taille et la méthode de croissance du tableau à partir de sont très importantes. Jetons un coup d'œil à travers le code.
/ ** * construit un tampon de chaîne sans caractères et une * capacité initiale de 16 caractères. * / public StringBuffer () {super (16); } / ** * construit un générateur de cordes sans caractères et une * capacité initiale de 16 caractères. * / public StringBuilder () {super (16); }Comme vous pouvez le voir, ces deux constructeurs par défaut indiquent que la taille du tableau par défaut est de 16.
Pourquoi 16? Je n'ai pas compris.
Quelle est la prochaine étape de la façon de grandir? Jetons un coup d'œil à la mise en œuvre de l'ajout
public abstractStringBuilder append (String str) {if (str == null) return appendNull (); int len = str.length (); AssurecapacityInternal (Count + Len); str.getchars (0, len, valeur, comte); Count + = len; retourner ceci; } / ** * Cette méthode a le même contrat que l'assurecapacité, mais n'est * jamais synchronisé. * / private void assurecapacityInternal (int minimumcapacity) {// Code de trop-flux if (minimumCapacity - value.length> 0) ExtendCapacity (minimumCapacity); } / ** * Ceci implémente la sémantique d'extension de l'assurécapacité sans vérification ou synchronisation de taille. * / void ExpandCapacity (int minimumCapacity) {int newcapacity = value.length * 2 + 2; if (newCapacity - minimumcapacity <0) newCapacity = minimumCapacity; if (newCapacity <0) {if (minimumCapacity <0) // débordera de nouveaux ouvrages ultofMemoryError (); newCapacity = Integer.max_value; } value = arrays.copyof (valeur, newCapacity); }Les trois méthodes ci-dessus expliquent comment augmenter la capacité.
Mettez la capacité actuelle * 2 + 2
Si la longueur nouvellement ajoutée est supérieure à cette valeur, réglé sur la valeur nouvellement ajoutée
Si débordez, jetez un overofMemoryerror
Implémentation de ToString dans StringBuffer
/ ** * Un cache de la dernière valeur renvoyée par ToString. Effacés * chaque fois que le stringbuffer est modifié. * / Char transitoire privé [] toStringCache; @Override public synchronisé stringbuffer append (string str) {toStringCache = null; Super.APPEND (STR); retourner ceci; } @Override public synchronisé chaîne toString () {if (toStringCache == null) {toStringCache = arrays.copyofrange (valeur, 0, count); } return new String (toStringCache, true); }Comme vous pouvez le voir, un tableau TostringCache est défini. Chaque fois que les données changent, ceci est défini sur NULL. Lorsque TOSTRING, prenez-le à nouveau des données actuelles.
Le mot-clé transitoire consiste à empêcher la sérialisation de ce tableau.
résumé
En fait, le code source de Java lui-même est relativement simple. Si vous pouvez commencer par le code source, vous pouvez comprendre de nombreux principes plus profondément. Cet article répertorie simplement certains codes source et explique brièvement les similitudes et les différences entre StringBuffer et StringBuilder. Les amis intéressés peuvent y jeter un œil.
L'article ci-dessus examine brièvement les similitudes et les différences entre StringBuilder et StringBuffer du point de vue du code source (analyse complète) est tout le contenu que je partage avec vous. J'espère que cela pourra vous donner une référence et j'espère que vous pourrez soutenir Wulin.com plus.