java笔记之stringbuffer 、stringbullider 类详解
StringBuffer : 由于String是不可变的,频繁修改会导致String对象泛滥,所以需要使用可变的字符串缓冲区类。
StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。看如下源码:
1 public synchronized StringBuffer reverse() { 2 super.reverse(); 3 return this; 4 } 5 6 public int indexOf(String str) { 7 return indexOf(str, 0); //存在 public synchronized int indexOf(String str, int fromIndex) 方法 8 }
StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。
相同情况下使用 StringBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。而在现实的模块化编程中,负责某一模块的程序员不一定能清晰地判断该模块是否会放入多线程的环境中运行,因此:除非确定系统的瓶颈是在 StringBuffer 上,并且确定你的模块不会运行在多线程模式下,才可以采用StringBuilder;否则还是用StringBuffer。
StringBuffer 特点:
- 默认缓冲区的容量是16。
stringbuffer底层依赖一个字符数组才能存储字符数据,该字符数组的默认初始容量是16,如果不够使用,自动增长1倍+2.
可以使用stringbuffer的capacity方法查看字符串的容量。要和length方法区分,length返回的是存储字符的个数。
1.StringBuffer : 线程安全的所有的缓冲区操作方法都是同步的。效率很低。
所以在实际使用时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用如果经常需要对一个字符串进行修改,例如插入、删除等操作,使用StringBuffer要更加适合一些。
注意:StringBuffer和String属于不同的类型,也不能直接进行强制类型转换,下面的代码都是错误的:
StringBuffer s = “abc”; //赋值类型不匹配
StringBuffer s = (StringBuffer)”abc”; //不存在继承关系,无法进行强转
注意:
在某些特别情况下, String 对象的字符串拼接其实是被 JVM 解释成了 StringBuffer 对象的拼接,所以这些时候 String对象的速度并不会比 StringBuffer 对象慢,而特别是以下的字符串对象生成中, String 效率是远要比 StringBuffer 快的:
String S1 = “This is only a” + “ simple” + “ test”;
StringBuffer Sb = new StringBuffer(“This is only a”).append(“ simple”).append(“ test”);
你会发现生成 String S1 对象的速度简直太快了,而这个时候 StringBuffer 居然在速度上一点都不占优势。其实这是 JVM 搞的鬼,这个
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;
这时候 JVM 会规规矩矩的按照原来的方式去做
String的concatenation(即+)操作利用了StringBuilder(或StringBuffer)的append方法实现,此时,对于上述情况,若s2,s3,s4采用String定义,拼接时需要额外创建一个StringBuffer(或StringBuilder),之后将StringBuffer转换为String;若采用StringBuffer(或StringBuilder),则不需额外创建StringBuffer。
1.1 添加方法(可存储任意类型)
初期,爆发户通过自己的努力,赚了点积蓄。将其存入银行
StringBuffer() 在创建对象的时候赋值
append() 在缓冲区的尾部添加新的文本对象
insert() 在指定的下标位置添加新的文本对象
public class TestStringBuffer { public static void main(String[] args) { StringBuffer stringBuffer=new StringBuffer("700"); //在创建对象的时候赋值 stringBuffer.append("00");//在缓冲区的尾部添加新的文本对象 stringBuffer.insert(3,"00");//在缓冲区的尾部添加新的文本对象
stringBuffer.append("万");
System.out.println("爆发户现在有:"+stringBuffer); } }
结果为:爆发户现在有:7000000万
1.2查看方法
渐渐的爆发户自我膨胀,失去自我,先查看自己有多少积蓄,然后开始挥霍。
toString() 返回这个容器的字符串
indexOf(String str) 返回第一次出现的指定子字符串在该字符串中的索引。
lastindexOf(String str) 返回最后一次出现的指定子字符串在该字符串中的索引。
substring(int start) 从开始的位置开始截取字符串
public class Stringbuffer01 {
public static void main(String[] args) {
StringBuffer stringBuffer =new StringBuffer();
stringBuffer.append("7000000万");
int index=stringBuffer.indexOf("0");
int last=stringBuffer.lastIndexOf("万");
String string=stringBuffer.substring(0, 5);
System.out.println("第一次出现的指定子字符串"+index);
System.out.println("最后一次出现的指定子字符串"+last);
System.out.println("截取后返回的字符串: "+string);
System.out.println("返回这个容器的字符串"+string.toString());
}
}
输出结果:
第一次出现的指定子字符串1
最后一次出现的指定子字符串7
截取后返回的字符串: 70000
返回这个容器的字符串70000
由此看出,爆发户的存款上最后一次出现万字的索引为7,第一次和中间都返回0,说明为整不带其他数字。可推算出存款为:7000000万
1.3修改
首先呢,爆发户先去环游世界,开公司,买豪宅。泡妞。。。。。。
replace(int start int endString str) 使用给定 String 中的字符替换此序列的子字符串中的字符。该子字符串从指定的 start 处开始,一直到索引 end - 1 处的字符
setCharAt(int index char ch) 指定索引位置替换一个字符
public class StringBuffer003 {
public static void main(String[] args) {
StringBuffer stringBuffer =new StringBuffer();
stringBuffer.append("7000000万");
stringBuffer.replace(2, 6, "");
System.out.println("首次挥霍后剩余:"+stringBuffer);
stringBuffer.setCharAt(0, '3');
System.out.println("再次挥霍后剩余:"+stringBuffer);
}
}
输出结果:
首次挥霍后剩余:700万
再次挥霍后剩余:300万
1.4删除
眼看所剩不多,买豪宅又是贷款,坐了抵押,爆发户决定去赌场试试运气,久而久之,身上的继续慢慢就被输光了
deleteCharAt() 指定删除索引处字符
delete(start, end) 指定删除开始和结束之间的内容
public class buffer {
public static void main(String[] args) {
StringBuffer stringBuffer=new StringBuffer();
stringBuffer.append("300万");
StringBuffer s =stringBuffer.deleteCharAt(1);
System.out.println("呆了一天后还剩:"+s);
s=s.delete(1, 3);
System.out.println("最后剩余(含有开始和结尾):"+s);
}
}
输出结果:
呆了一天后还剩:30万
最后剩余(含有开始和结尾):3
1.5其他方法
public StringBuffer reverse(); //反转
public void trimToSize() 该方法的作用是将StringBuffer对象的中存储空间缩小到和字符串长度一样的长度,减少空间的浪费。
对于三者使用的总结: 1.如果要操作少量的数据用 ———> String
2.单线程操作字符串缓冲区 下操作大量数据 ———> StringBuilder
3.多线程操作字符串缓冲区 下操作大量数据 ———> StringBuffer