面试题:String,StringBuilder,StringBuffer三者的区别
摘要:总结Java中的String,StringBuilder,StringBuffer三者的区别和联系,介绍后两者的扩容机制。
Java中的String,StringBuilder,StringBuffer这三个类之间的区别主要集中在两个方面,即运行速度和线程安全这两方面。
String:字符串常量,这就导致每次对String的操作都会创建新的String对象,不仅效率低,而且浪费有限的内存空间;故适用于少量的字符串操作的场景。
StringBuilder:线程不安全,适用于单线程下在字符缓冲区进行大量操作的情况。
StringBuffer:线程安全,适用于多线程下在字符缓冲区进行大量操作的情况。
一般情况下,操作执行速度从快到慢依次是:StringBuilder > StringBuffer > String。这种比较是相对的,不是绝对的。String最慢的原因:String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,进行值操作的时候,是需要重新创建String对象的,但后两者的对象是变量,是可以更改的。
StringBuilder 和 StringBuffer 扩容机制:需要的最小容量(已经存储的数据长度+准备存储的数据的长度)是否大于底层char数组的长度,如果大于就按照原来长度*2+2扩容。
为什么扩容时要+2?请注意入参capacity的数据类型是int,故传入参数可以是0,在参数是0的情况下,0<<1运算结果也是0,导致以0初始化数组的时候必然会报错,所以从设计的安全性视角考虑,防止出现报错,选择了+2。
/**
* Constructs a string builder with no characters in it and an
* initial capacity specified by the {@code capacity} argument.
*
* @param capacity the initial capacity.
* @throws NegativeArraySizeException if the {@code capacity}
* argument is less than {@code 0}.
*/
public StringBuilder(int capacity) {
super(capacity);
}
初始化StringBuilder的容量。构造器StringBuilder() 会创建一个默认大小(通常是16)的字符数组。在使用中,如果需要扩容,就需要重新分配内存,创建一个更大的char数组,并将原先的数组复制过来,再丢弃旧的数组。在大多数情况下,可以在创建 StringBuilder 的时候指定大小,从而避免在容量不够的时候自动扩容,以提高性能。
示例:StringBuilder sb = new StringBuilder(700)
。
作为程序员,要有“刨根问底”的精神。知其然,更要知其所以然。这篇文章希望能抽丝剥茧,还原背后的原理。