Java StringBuffer和StringBuider

今天来讲讲StringBuffer和StringBuilder这两个类的区别

说这两个类之前,先来简单提一提String这个类,String的值是不可变的,每次对String的操作都会生成一个新的String对象,不仅效率低,而且占用大量的内存空间。

那么有没有一种办法可以操作字符串并且效率不挫,还不占用大量的内存空间呢?

答案是有,这就得说说StringBuffer和StringBuider这两个类了。

先来说说StringBuffer类

StringBuffer类和String类一样,也用来表示字符串,但是StringBuffer的内部实现方式和String类不同,在进行字符串处理时,不生成新的对象,就在内存上也要优于String。

StringBuffer默认分配16字节长度的缓冲区,当字符串超过大小时,会自动增加缓冲区长度,而不是生成新的对象。

StringBuffer不像String,没有简写,只能通过new关键字来创建一个StringBuffer对象,例如:

StringBuffer sb1=new StringBuffer();//默认分配6字节长度的缓冲区
StringBuffer sb2=new StringBuffer(32);//分配32字节长度的缓冲区
StringBuffer sb3=new StringBuffer("Hello World");//在缓冲区中存放了字符串,并在字符串后面预留了16个字节长度的缓冲区
StringBuffer类的主要常用方法

StringBuffer类中的方法主要偏向对字符串的操作,例如追加、插入、替换和删除等。实际开发中,如果要对一个字符串进行频繁的修改,建议使用StringBuffer。

  • append(String str)

   把str字符串追加到此StringBuffer对象后

StringBuffer sb=new StringBuffer("Hello");
sb.append("World");

    此时追加后,对象sb的值将变成“HelloWorld”,注意时sb指向的内容变了,而不是sb的指向变了。

    字符串的“+”操作实际上也是先创建一个StringBuffer对象,然后调用append()方法将字符串拼接起来,最后调用toString()方法转换成字符串。

  • charAt(int index)

    根据索引返回此处的char值

  • delete(int beginIndex,int endIndex)

   移除从beginIndex索引开始到endIndex索引结束的字符串

StringBuffer sb=new StringBuffer("HelloWorld");//此时创建对象为“HelloWorld”
sb.delete(3, 5);//删除索引从3到5之前的字符(下标从0开始),结果为“HelWorld”
  • deleteCharAt(int index)

    移除索引index处的char值

  • indexOf(String str)

    返回第一次出现指定子字符串在该字符串中的索引

  • insert(String str,int fromIndex)

   将String类型的参数str插入到指定索引fromIndex处

  • lastIndexOf(String str)

    返回最后一次出现指定子字符串在该字符串中的索引

  • length()

    返回此字符串的长度

  • replace(int start , int end , String str)

    使用给定String中的字符替换此序列的子字符串中的字符

StringBuffer sb=new StringBuffer("HelloWorld");//此时创建对象为“HelloWorld”
sb.replace(3, 5, "1111");//替换完之后变成了“Hel1111World”

    注意:这里替换实际上等同于先把索引从3到5之前的字符移除,然后在把字符串“1111”从3开始插入,然后 在加上后面剩余的字符。

  • reverse()

    将此字符序列反转形式返回

StringBuffer sb=new StringBuffer("HelloWorld");//此时创建对象为“HelloWorld”
System.out.println(sb.reverse().toString());//反转序列为“dlroWolleH”
  • subString(int start , int end)

      截取字符串

StringBuilder类

StringBuilder类和StringBuffer类功能基本相似,方法也差不多,主要区别在于StringBuffer类的方法是多线程安全的,而StringBuilder类的方法不是线程安全的,所以相比较StringBuffer,StringBuilder的执行效率能更快一些。

而StringBuffer、StringBuilder和String都实现了CharSequence接口

CharSequence是一个定义字符串操作的接口,它只包括length()、charAt(int index)、subSequence(int start,int end)这几个方法。

StringBuffer、StringBuilder、String对CharSequence接口的实现工程不一样,如下图所示:

可见,String类是直接实现了CharSequence接口,StringBuilder和StringBuffer都是可变的字符序列,它们都继承于AbstractStringBuilder类,而AbstractStringBuilder类则实现了CharSequence接口。

效率对比

//分别对String、StringBuffer、StringBuilder这三个类的字符串对象把字符‘A’加了100000次
int n=100000;
char c='A';
String str="";
StringBuffer strBuffer=new StringBuffer("");
StringBuilder strBuilder=new StringBuilder("");
		
//String对象
long startTime1=System.currentTimeMillis();//获得当前时间,单位是long型
for(int i=1;i<n;i++){
    str+=c;
}
long endTime1=System.currentTimeMillis();
System.out.println("String: "+(endTime1-startTime1)+" ms");
		
//StringBuffer对象
long startTime2=System.currentTimeMillis();
for(int i=1;i<n;i++){
    strBuffer.append(c);
}
long endTime2=System.currentTimeMillis();//获得当前时间,单位是long型
System.out.println("StringBuffer: "+(endTime2-startTime2)+" ms");
		
//StringBuilder对象
long startTime3=System.currentTimeMillis();
for(int i=1;i<n;i++){
	strBuilder.append(c);
}
long endTime3=System.currentTimeMillis();//获得当前时间,单位是long型
System.out.println("StringBuilder: "+(endTime3-startTime3)+" ms");

运行结果:

String: 5337 ms
StringBuffer: 3 ms
StringBuilder: 1 ms

结果很明显,StringBuffer的执行效率比String快千倍,这个差异随着叠加次数的增加越来越明显,而StringBuilder则由于不用考虑线程安全问题,效率比StringBuffer还要快。

所以,强烈建议再涉及大量对字符串操作时使用StringBuffer或者StringBuilder。

而StringBuffer类是线程安全的,而StringBuilder类不是线程安全的,读者可以依情况选择使用哪个类。

结论

线程安全:
  • StringBuffer:线程安全
  • StringBuilder:线程不安全
速度:
  • 一般情况下,速度从快到慢为StringBuilder > StringBuffer > String,当然这是相对的,不是绝对的。
使用场景 :

当操作少量数据时使用String

不考虑线程安全问题并操作大量数据使用StringBuilder

需要考虑线程安全问题并操作大量数据使用StringBuffer





猜你喜欢

转载自blog.csdn.net/xkfanhua/article/details/80551645
今日推荐