通常,当涉及到StringBuilder或StringBuffer时,应该考虑另一个,然后在脑海中询问使用另一个是否更合适。
为什么呢,请继续往下看。 当然,如果你已经熟悉两者,当然没有必要这么做。 本文介绍了StringBuffer和StringBuilder,最后
string (如果您想了解string,请单击此处)、StringBuffer和StringBuilder之间的差异。
什么是字符串缓冲区
StringBuffer是线程安全的可变字符串,其父类是AbstractStringBuilder。 到此为止你可能会怀疑,缓冲不就是缓冲的意思吗? 应该称为字符串缓冲区。
是的。 这两种称呼都没有问题。 Buffer之所以作为缓冲区,是因为用于存储字符串(具体所需值)的内存空间已预先打开了一定程度。
基础数据结构:字符数组;
//*
* thevalueisusedforcharacterstorage。
*/
char[] value;
常用方法: append ()、insert ()、reverse (),其中append添加; 插入是插入; reverse ()函数用于反转字符串。
刚加入Java的时候,经常遇到给予字符串的问题。 而且,需要写完成这个功能的方法。 那时,不知道有这个方法,惊讶的是在文字排列上画了一个循环。
这里只列举了一部分,但详细方法可以在JDK的源代码中找到
append () )
/* * @ throwsindexoutofboundsexception { @ inherit doc }
*@see#length (()/) overridepublicsynchronizedvoidsetcharat (index,charch ) if ) (index0)|) index=count
toStringCache=null;
value[index]=ch;
}
@ overridepublicsynchronizedstringbufferappend (objectobj ) )。
toStringCache=null; super.append(string.valueof ) obj ); 返回时间;
}
@ overridepublicsynchronizedstringbufferappend {
toStringCache=null; super.append(str; 返回时间;
}
insert () )
/* * @ throwsstringindexoutofboundsexception { @ inherit doc }
* @ since 1.2 */@ overridepublicsynchronizedstringbufferinsert (intindex,char[] str,intoffset,intlen ) ) ) )
{
toStringCache=null; super.insert(index,str,offset,len ); 返回时间;
}/* * * @ throwsstringindexoutofboundsexception { @ inherit doc } */@ overridepublicsynchronizedstringbufferinsert (insert )
toStringCache=null; super.insert(offset,string.valueof ) (obj ); 返回时间;
}
reverse ) )字符串的反转。 在这里,您可以看到真正的反转逻辑是调用父类的reverse方法。
/* * @ since JDK1.0.2*/@ overridepublicsynchronizedstringbufferreverse (
toStringCache=null; super.reverse (; 返回时间;
}
reverse ) )父类的实现。
/* * * causesthischaractersequencetobereplacedbythereverseof
* the sequence.ifthereareanysurrogatepairsincludedinthe
* sequence,thesearetreatedassinglecharactersforthe
* rev
erse operation. Thus, the order of the high-low surrogates* is never reversed.
*
* Let n be the character length of this character sequence
* (not the length in {@codechar} values) just prior to
* execution of the {@codereverse} method. Then the
* character at index k in the new character sequence is
* equal to the character at index n-k-1 in the old
* character sequence.
*
*
Note that the reverse operation may result in producing
* surrogate pairs that were unpaired low-surrogates and
* high-surrogates before the operation. For example, reversing
* "u005CuDC00u005CuD800" produces "u005CuD800u005CuDC00" which is
* a valid surrogate pair.
*
*@returna reference to this object.*/
publicAbstractStringBuilder reverse() {boolean hasSurrogates = false;int n = count - 1;for (int j = (n-1) >> 1; j >= 0; j--) {int k = n -j;char cj =value[j];char ck =value[k];
value[j]=ck;
value[k]=cj;if (Character.isSurrogate(cj) ||Character.isSurrogate(ck)) {
hasSurrogates= true;
}
}if(hasSurrogates) {
reverseAllValidSurrogatePairs();
}return this;
}
StringBuilder是什么
StringBuilder是一个可变的字符序列。
底层数据结构,常用方法:同StringBuffer
String,StringBuffer,StringBuilder 比较
通过了解String的源码可以知道,String对象的值是被final修饰符修饰的,所以一旦确定值,再去做变更就必须要重新指定引用地址,新引用地址意味着要开辟新的栈内存,
那么这里就会出现旧的引用被浪费,需要等待回收机制对其进行回收。
如果现在有一个字符串需要频繁改变,此时就必须要用StringBuilder或者StringBuffer。因为StringBuffer和StringBuilder都是字符数组,我们知道
数组的长度是可变的。一旦字符串发生变化,不需要和String那样重新开辟栈内存,而是在原来的基础上对数组进行内容进行变更,如果内容超过默认长度的话则会自动扩充,以满足变更之后的需求。
细心的朋友可能已经发现在介绍StringBuilder的时候,对于底层数据结构和常用的方法使用的是和StringBuffer相同,唯独第一句话明确的写出来了。因为StringBuffer和StringBuilder的最主要的区别就在于,StringBuffer是线程安全的而StringBuilder不是线程安全的。
归结起来就是String的值是final的,变更需要重新创建栈内存,因此不但会造成旧的栈内存空间的浪费,而且由此导致更多的垃圾需要被回收机制回收,耗费性能。
StringBuffer和StringBuilder则没有此弊端。而StringBuffer相比StringBuider适合多线程因为它是线程安全的所有操作值得方法都用synchronized修饰;StringBuilder则适合单线程的场景,没有同步方法效率较高相比StringBuffer来说。
结语
以上就是三者的异同分析,StringBuffer是在JDK1.0就有的,而StringBuilder在JDK1.5才加入,依据比对结果来看应该是为了让程序在单线程有更好的表现才曾加的StringBuilder。下面是StringBuilder源码中的一句介绍。
A mutable sequence of characters. This class provides an API compatible
with {@code StringBuffer}, but with no guarantee of synchronization.
如果对StringBuffer和StringBuilder的默认长度是多少,在数据超过默认长度之后,底层数组又是如何扩充感兴趣的可以自己去研究一下源码。
世上无难事只怕有心人。共勉之。