1. StringBuilder的背景信息
在Java String类中,字符串是不可变的对象,因此如果需要修改一个字符串,就需要创建一个新的String对象。这种机制可能会导致内存浪费和可维护性差的问题。Java StringBuilder为此而来。 StringBuilder提供了一种高效的字符串操作方式。使用StringBuilder可以避免在每次字符串操作时都重新创建一个新的String对象。它是自动扩容的,也可以手工调整其容量。其主要特点如下:- StringBuilder对象的长度和内容可以修改
- StringBuilder对象可以在进行字符串操作时不需要额外开辟空间
- StringBuilder对象可以自由进行扩容,缓冲器与创建字符数组的效果类似
- StringBuilder对象可以直接和String对象进行互相转换
2. StringBuilder的详细阐述
一、StringBuilder与String的区别
StringBuilder对象可以在创建后进行内容的追加和修改,因此StringBuilder对象相关的API方法会比较多,而且在Java的API中,StringBuilder类和String类基本是对应的,两者有很多相似的方法。 不仅如此, stringBuilder还有一些独特的方法和属性使它更加实用。例如,StringBuilder对象可以通过反向追加字符串来构造一个全新的字符串,这在某些情况下会更加高效。二、StringBuilder容量和长度的关系
当创建一个StringBuilder时,它的默认容量为16个字符(如有需要可以通过构造函数指定容量大小)。如果需要在StringBuilder中添加的字符超出其当前容量,StringBuilder会自动进行扩容。扩容时,产生的新数组大小为原数组大小的2倍+2。三、StringBuilder的方法
StringBuilder类中有很多方法可以对其进行操作,下面列举几个最常用的方法://构造函数 StringBuilder() //构造一个空的字符串构建器,容量为默认大小16 StringBuilder(CharSequence seq) //构造一个字符串构建器,该构建器包含与指定的CharSequence相同的字符 //添加方法,将string,char,StringBuilder对象或其它对象加入再修改文本 append(String str) //将指定字符串追加到此字符序列 append(char c) //将指定字符追加到此字符序列 append(StringBuffer sb) //将指定StringBuffer追加到此字符序列 append(CharSequence s) //将指定CharSequence追加到此字符序列 append(Object obj) //将指定对象的字符串表示形式追加到此字符序列 append(StringBuilder sb) //将指定StringBuilder追加到此字符序列 append(CharSequence s, int start, int end) //将指定CharSequence的子序列追加到此字符序列 //插入方法,在任意位置插入新的文本 insert(int offset, String str) //将指定字符串插入此字符序列中 insert(int offset, CharSequence s) //将指定CharSequence插入此字符序列中 insert(int dstOffset, CharSequence s, int start, int end) //将指定CharSequence字符子集插入此字符序列 insert(int offset, boolean b) //将boolean参数插入此字符序列 insert(int offset, char c) //将char参数插入此字符序列中 insert(int offset, int i) //将int参数插入此字符序列中 insert(int offset, long l) //将long参数插入此字符序列中 insert(int offset, float f) //将float参数插入此字符序列中 insert(int offset, double d) //将double参数插入此字符序列中
3. StringBuilder小标题
1. StringBuilder与String的性能对比
在进行多次追加操作时,如果使用String对象进行操作,就需要每次创建一个新的对象。这样的话,在容量可预估的情况下,可以使用StringBuilder进行初始化,可以在程序的初始执行期就分配足够的内存以避免重新分配内存。 示例代码:public static void main(String[] args) { //使用String long startTime = System.currentTimeMillis(); String s = ""; for (int i = 0; i < 10000; i++) { s += i; } long endTime = System.currentTimeMillis(); System.out.println("String time cost: " + (endTime - startTime) + "ms"); //使用StringBuilder startTime = System.currentTimeMillis(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < 10000; i++) { sb.append(i); } endTime = System.currentTimeMillis(); System.out.println("StringBuilder time cost: " + (endTime - startTime) + "ms"); }输出结果: String time cost: 38ms
StringBuilder time cost: 1ms 从上述代码和结果可知,使用StringBuilder进行字符串追加的效率要大大高于使用String。因此,在处理字符序列时,如果需要对其进行多次操作,则应优先考虑使用StringBuilder。
2. StringBuilder的线程安全问题
在单一线程环境下,StringBuilder比StringBuffer要快很多,但是在多线程的情况下StringBuilder是线程不安全的。 如果需要在多线程环境下使用StringBuilder,可以使用java.util.concurrent.atomic.AtomicReference,java.util.concurrent.atomic.AtomicLongFieldUpdater等线程安全类来进行替代实现。3. StringBuilder的容量和长度的控制
StringBuilder默认的初始化容量为16个字符,如果在使用时发现StringBuilder未参考原始字符串的容量进行设定初始化容量,则每次进行扩容的时候都会重新申请新的内存空间对象,这样的开销将越来越大,直到StringBuilder的长度超过需要的字符串长度,扩容次数达到一定数量后,StringBuilder操作效率将直线下降。 因此,在使用StringBuilder时,如果提前知道字符串的长度,可以使用构造函数或者.ensureCapacity()方法对容量进行初始化。StringBuilder sb1 = new StringBuilder(); //默认容量16 StringBuilder sb2 = new StringBuilder(32); //容量为32 sb1.ensureCapacity(64); //容量是64