Maison > Java > javaDidacticiel > Analyse des différences entre Java String, StringBuffer et StringBuilder

Analyse des différences entre Java String, StringBuffer et StringBuilder

高洛峰
Libérer: 2017-01-22 11:41:36
original
1492 Les gens l'ont consulté

Je crois que tout le monde connaît déjà la différence entre String et StringBuffer, mais on estime que de nombreux camarades ne comprennent toujours pas les principes de fonctionnement de ces deux classes. Aujourd'hui, je vais passer en revue ce concept pour tout le monde. une nouvelle classe d'opérations sur les caractères introduite dans J2SE 5.0 - StringBuilder. Alors, quelles sont les différences entre ce StringBuilder et StringBuffer et la classe String que nous avons rencontrée pour la première fois ? Lequel devrions-nous utiliser dans différentes situations ? J'aimerais partager mon point de vue sur ces catégories, et j'espère aussi que chacun pourra donner son avis. Tout le monde a fait des erreurs, et en les corrigeant, c'est une bonne opportunité d'apprendre.

En bref, la principale différence de performances entre le type String et le type StringBuffer est que String est un objet immuable (pourquoi ? Demandez aux concepteurs de Java, pourquoi String n'est-il pas un type natif ?) Par conséquent, à chaque fois Lorsque vous modifiez le type String, cela équivaut en fait à générer un nouvel objet String, puis à pointer le pointeur vers le nouvel objet String. Par conséquent, il est préférable de ne pas utiliser String pour les chaînes dont le contenu change fréquemment, car à chaque fois un objet est modifié. généré, cela affectera les performances du système. Surtout lorsqu'il y a trop d'objets non référencés dans la mémoire, le GC de la JVM commencera à fonctionner et la vitesse sera certainement assez lente. Voici un exemple peu approprié :

String S1 = "abc"; 
For(int I = 0 ; I < 10000 ; I ++) // For 模拟程序的多次调用 
{ 
S1 + = "def"; 
S1 = "abc"; 
}
Copier après la connexion

Si c'est le cas, une fois la boucle for terminée, si les objets en mémoire n'ont pas été nettoyés par le GC, il y aura plus de 20 000 objets en mémoire. C’est un nombre étonnant, et s’il s’agit d’un système utilisé par de nombreuses personnes, ce nombre n’est pas très grand, donc chacun doit être prudent lorsqu’il l’utilise.

Si vous utilisez la classe StringBuffer, le résultat sera différent à chaque fois, le résultat sera une opération sur l'objet StringBuffer lui-même, au lieu de générer un nouvel objet puis de changer la référence de l'objet. Donc, en général, nous recommandons d'utiliser StringBuffer, en particulier lorsque les objets chaîne changent fréquemment. Dans certains cas particuliers, la concaténation de chaînes d'objets String est en fait interprétée par la JVM comme la concaténation d'objets StringBuffer, donc dans ces cas, la vitesse des objets String ne sera pas plus lente que celle des objets StringBuffer, et en particulier les objets chaîne suivants sont généré, l'efficacité de String est beaucoup plus rapide que StringBuffer :

String S1 = "This is only a" + " simple" + " test"; 
StringBuffer Sb = new StringBuilder("This is only a").append(" simple").append(" test");
Copier après la connexion

Vous serez surpris de constater que la vitesse de génération des objets String S1 est tout simplement trop rapide, et pour le moment, StringBuffer n'est pas du tout rapide. Dominer. En fait, c'est une astuce de la JVM. Aux yeux de la JVM, ceci

String S1 = "This is only a" + " simple" + "test"; 其实就是: String S1 = "This is only a simple test"; 所以当然不需要太多的时间了。但大家这里要注意的是,如果你的字符串是来自另外的 String 对象的话,速度就没那么快了,譬如: 
String S2 = "This is only a"; 
String S3 = " simple"; 
String S4 = " test"; 
String S1 = S2 +S3 + S4;
Copier après la connexion

A ce moment, la JVM le fera de la manière originale, et la vitesse de génération des objets S1 sera ne soit pas aussi rapide qu'avant, nous pourrons faire un test pour le vérifier plus tard.

De là, nous obtenons la première conclusion : dans la plupart des cas, StringBuffer > String

Et comment StringBuilder se compare-t-il à eux ? Permettez-moi d'abord de donner une brève introduction. StringBuilder est une classe nouvellement ajoutée dans JDK5.0. La différence entre elle et StringBuffer est la suivante (source JavaWorld) :

Java.lang.StringBuffer est une variable thread-safe. séquence de caractères. Un tampon de chaîne similaire à String, mais ne peut pas être modifié. Les tampons de chaînes peuvent être utilisés en toute sécurité par plusieurs threads. Ces méthodes peuvent être synchronisées si nécessaire, de sorte que toutes les opérations sur une instance particulière semblent se produire dans un ordre sériel cohérent avec l'ordre des appels de méthode effectués par chaque thread impliqué.

Chaque tampon de chaîne a une certaine capacité. Tant que la longueur de la séquence de caractères contenue par le tampon de chaîne ne dépasse pas cette capacité, il n'est pas nécessaire d'allouer un nouveau tableau de tampon interne. Cette capacité est automatiquement augmentée en cas de débordement du buffer interne. À partir du JDK 5.0, une classe équivalente pour une utilisation avec un seul thread a été ajoutée à cette classe, StringBuilder. La classe StringBuilder doit généralement être utilisée de préférence à cette classe car elle prend en charge toutes les mêmes opérations mais est plus rapide car elle n'effectue pas de synchronisation.

Mais il n'est pas sûr d'utiliser une instance de StringBuilder avec plusieurs threads. Si une telle synchronisation est requise, il est recommandé d'utiliser StringBuffer.

Je pense que tout le monde peut comprendre la différence entre eux, alors faisons une déduction générale ci-dessous :

Dans la plupart des cas StringBuilder > StringBuffer

Par conséquent, selon le théorème de transfert de cette inégalité : Dans la plupart des cas StringBuilder > StringBuffer > String

Maintenant qu'il existe un tel résultat de dérivation, faisons un test pour le vérifier :

Test Le code est le suivant :

public class testssb { 

/** Creates a new instance of testssb */ 
final static int ttime = 10000;// 测试循环次数 
public testssb() { 
} 

public void test(String s){ 
long begin = System.currentTimeMillis(); 
for(int i=0;i<ttime;i++){ 
s += "add"; 
} 
long over = System.currentTimeMillis(); 
System.out.println(" 操作 "+s.getClass().getName()+" 类型使用的时间为: " + (over - begin) + " 毫秒 " ); 
} 

public void test(StringBuffer s){ 
long begin = System.currentTimeMillis(); 
for(int i=0;i<ttime;i++){ 
s.append("add"); 
} 
long over = System.currentTimeMillis(); 
System.out.println(" 操作 "+s.getClass().getName()+" 类型使用的时间为: " + (over - begin) + " 毫秒 " ); 
} 

public void test(StringBuilder s){ 
long begin = System.currentTimeMillis(); 
for(int i=0;i<ttime;i++){ 
s.append("add"); 
} 
long over = System.currentTimeMillis(); 
System.out.println(" 操作 "+s.getClass().getName()+" 类型使用的时间为: " + (over - begin) + " 毫秒 " ); 
} 

// 对 String 直接进行字符串拼接的测试 
public void test2(){ 
String s2 = "abadf"; 
long begin = System.currentTimeMillis(); 
for(int i=0;i<ttime;i++){ 
String s = s2 + s2 + s2 ; 
} 
long over = System.currentTimeMillis(); 
System.out.println(" 操作字符串对象引用相加类型使用的时间为: " + (over - begin) + " 毫秒 " ); 
} 

public void test3(){ 
long begin = System.currentTimeMillis(); 
for(int i=0;i<ttime;i++){ 
String s = "abadf" + "abadf" + "abadf" ; 
} 
long over = System.currentTimeMillis(); 
System.out.println(" 操作字符串相加使用的时间为: "+ (over - begin) + " 毫秒 " ); 
} 

public static void main(String[] args){ 
String s1 ="abc"; 
StringBuffer sb1 = new StringBuffer("abc"); 
StringBuilder sb2 = new StringBuilder("abc"); 

testssb t = new testssb(); 
t.test(s1); 
t.test(sb1); 
t.test(sb2); 
t.test2(); 
t.test3(); 
} 
}
Copier après la connexion

以上代码在 NetBeans 5.0 IDE/JDK1.6 上编译通过,循环次数 ttime 为 10000 次的测试结果如下: 
操作 java.lang.String 类型使用的时间为: 4392 毫秒 
操作 java.lang.StringBuffer 类型使用的时间为: 0 毫秒 
操作 java.lang.StringBuilder 类型使用的时间为: 0 毫秒 
操作字符串对象引用相加类型使用的时间为: 15 毫秒 
操作字符串相加使用的时间为: 0 毫秒 

好像还看不出 StringBuffer 和 StringBuilder 的区别,把 ttime 加到 30000 次看看: 
操作 java.lang.String 类型使用的时间为: 53444 毫秒 
操作 java.lang.StringBuffer 类型使用的时间为: 15 毫秒 
操作 java.lang.StringBuilder 类型使用的时间为: 15 毫秒 
操作字符串对象引用相加类型使用的时间为: 31 毫秒 
操作字符串相加使用的时间为: 0 毫秒 

StringBuffer 和 StringBuilder 的性能上还是没有太大的差异,再加大到 100000 看看,这里就不加入对 String 类型的测试了,因为对 String 类型这么大数据量的测试会很慢滴…… 
操作 java.lang.StringBuffer 类型使用的时间为: 31 毫秒 
操作 java.lang.StringBuilder 类型使用的时间为: 16 毫秒 

能看出差别了,但其中有多次的测试结果居然是 StringBuffer 比 StringBuilder 快,再加大一些到 1000000 看看(应该不会当机吧?): 
操作 java.lang.StringBuffer 类型使用的时间为: 265 毫秒 
操作 java.lang.StringBuilder 类型使用的时间为: 219 毫秒 

有些少区别了,而且结果很稳定,再大点看看, ttime = 5000000 : 

······ Exception in thread "main" java.lang.OutOfMemoryError: Java heap space ······ 

呵呵,算了,不去测试了,基本来说都是在性能上都是 StringBuilder > StringBuffer > String 的了。

更多Java之String、StringBuffer、StringBuilder的区别分析相关文章请关注PHP中文网!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal