Java StringBuffer 和StringBuilder

简介:

其实在上面的文章中我已经阐述过了什么是String,其实,String三姐妹中还有两个非常丰满的存在:StringBuffer老大姐和StringBuilder小妹妹.
首先,前面我们说过String是不能被修改的,无论你如何对String进行赋值(+)都会在字符串常连池里面生成一个值.并且把这个值得地址引用给String变量,所以,只要是玩String后面添加东西,都是创建一个全新的JavaString对象.这样,我们可以来做个实验:
//本来
一开始是想计算五百次的String添加计算的,kanla9ishi天真了,那么五万次呢....

class StringTest {
    public static void main(String[] args) {
        //在这里定义一个循环结构,循环五百万次.我们开你一下耗时:
        long start = System.currentTimeMillis();
        int x = 50000;
        String value = "";
        for (int i = 0; i < x; i++) {
            value += i;
        }
        long stop = System.currentTimeMillis();
        System.out.println("String 总共耗时为: " + (stop - start)/1000+"秒");
    }
}

输出:
String 总共耗时为: 6秒

现在来看StringBUffderder的情况:注意时间单位

class StringBufferTest2{
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        int w = 5000000;
        StringBuffer stringBuffer = new StringBuffer();
        for(int i = 0;i<w ;i++){
            stringBuffer.append(i);
        }
        long stop = System.currentTimeMillis();
        System.out.println("StringBuffer 总共耗时为: " + (stop - start)+"毫秒");
    }
}

输出:
StringBuffer 总共耗时为: 308毫秒

然后...

class StringBudilerTest2{
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        int y = 5000000;
        StringBuilder stringBuilder = new StringBuilder();
        for(int i = 0;i<y ;i++){
            stringBuilder.append(i);
        }
        long stop = System.currentTimeMillis();
        System.out.println("StringBudiler: 总共耗时为: " + (stop - start)+"毫秒");
    }
}

输出:
.StringBudiler: 总共耗时为: 240毫秒
大家可以很明显的看出来了是怎么一回事.String循环五万次,了6000毫秒,而Stringbuffer循环添加五百万个只用了300毫秒!!!当然Stringbuilder只用了200毫秒.我的天,这是什么情况?
其实,为什么String三姐妹这件的差距这么的,就在于我开篇所说的,对于String来说,没错往已有的字符串后面追加内容,都是一个新的对对象,是对象就需要去给他开辟内存等等一些列复杂的炒作,但是,记住,但是@@@Stringbuffer和Stringbudiler在已有的字符串后面追加,其实是在修应该这个已经存在了的String对象,而没有创建新的对象!这既是为什么有这么大差距的原因了..是的,就是这样的....
那么...下一个问题.为什么会有两个高速修改字符类型的类?Stringbuffer和StringBudiler?
其实从上面的数据也可以看出一点,Stringbuffer的速度没有StrinhBuilder的速度快的,这是因为,StringBuffer是一个线程安全的类,你可以从他的源代码看到他的所有方法第都添加了synchronized关键字来保证线程安全.而StringBuild没有这种限制.如何选择就得看你的业务觉得了.
最后一个问题.Stringbuffer和StringBudiler还有提升速度的空间吗?
答案是有的.通过分析源代码我们可以看到一个非常现实的东西,那就是,Sb们都有一个初始的容量.其值为16

class StringBufferAndStringBufiler{
    public static void main(String[] args) {
        StringBuffer stringBuffer = new StringBuffer();
        int capacity = stringBuffer.capacity();
        System.out.println("stringBuffer的初始容量: " + capacity);
        StringBuilder stringBuilder = new StringBuilder();
        int capacity1 = stringBuffer.capacity();
        System.out.println("stringBuilder的初始容量: " + capacity1);

    }
}

输出:
stringBuffer的初始容量: 16
stringBuilder的初始容量: 16

容量是什么?容量就是这个sb能装多少的内容!这枚理解没毛病的

class StringBufferAndStringBufiler{
    public static void main(String[] args) {
        StringBuffer stringBuffer = new StringBuffer("123");
        int capacity = stringBuffer.capacity();
        System.out.println("stringBuffer的现有容量: " + capacity);
        StringBuilder stringBuilder = new StringBuilder("123");
        int capacity1 = stringBuffer.capacity();
        System.out.println("stringBuilder的现有容量: " + capacity1);

    }
}

输出:
stringBuffer的现有容量: 19
stringBuilder的现有容量: 19
以此可以看出,容量是可以改变的,那么他是在什么时候去改变你的呢?
看源代码:
添加long新类型时:

public AbstractStringBuilder append(long l) {
    if (l == Long.MIN_VALUE) {
        append("-9223372036854775808");
        return this;
    }
    int appendedLength = (l < 0) ? Long.stringSize(-l) + 1
                                 : Long.stringSize(l);
    int spaceNeeded = count + appendedLength;
    ensureCapacityInternal(spaceNeeded);
    Long.getChars(l, spaceNeeded, value);
    count = spaceNeeded;
    return this;
}
添
加```  
inr类型时:

public AbstractStringBuilder append(int i) {

if (i == Integer.MIN_VALUE) {
    append("-2147483648");
    return this;
}
int appendedLength = (i < 0) ? Integer.stringSize(-i) + 1
                             : Integer.stringSize(i);
int spaceNeeded = count + appendedLength;
ensureCapacityInternal(spaceNeeded);
Integer.getChars(i, spaceNeeded, value);
count = spaceNeeded;
return this;

}

从中都可以看到一个ensureCapacityInternal方法,该方法就是在检查当前容量是否够用.如果不够则扩容.
了解这个对速度的提升有什么帮助呢?
我们可以让他不去做扩容,那么相对的时间就可以减少了.这就要求我闷在初始化sb的时候要给一个大约的初始容量.比如:

class StringBufferTest2{

public static void main(String[] args) {
    long start = System.currentTimeMillis();
    int w = 5000000;
    StringBuffer stringBuffer = new StringBuffer(1000000);//初始化stringBuffer的容量
    for(int i = 0;i<w ;i++){
        stringBuffer.append(i);
    }
    long stop = System.currentTimeMillis();
    System.out.println("StringBuffer 总共耗时为: " + (stop - start)+"毫秒");
}

}

class StringBudilerTest2{

public static void main(String[] args) {
    long start = System.currentTimeMillis();
    int y = 5000000;
    StringBuilder stringBuilder = new StringBuilder(10000000);//初始化stringBuilder的容量
    for(int i = 0;i<y ;i++){
        stringBuilder.append(i);
    }
    long stop = System.currentTimeMillis();
    System.out.println("StringBudiler: 总共耗时为: " + (stop - start)+"毫秒");
}

}

对于这个值到底该是多少 ,当然就得靠你去估计一下咯.
至于sb们的一些方法,大家可以去看一下API其实和String没有多少区别的.
目录
相关文章
|
4月前
|
安全 Java API
【Java字符串操作秘籍】StringBuffer与StringBuilder的终极对决!
【8月更文挑战第25天】在Java中处理字符串时,经常需要修改字符串,但由于`String`对象的不可变性,频繁修改会导致内存浪费和性能下降。为此,Java提供了`StringBuffer`和`StringBuilder`两个类来操作可变字符串序列。`StringBuffer`是线程安全的,适用于多线程环境,但性能略低;`StringBuilder`非线程安全,但在单线程环境中性能更优。两者基本用法相似,通过`append`等方法构建和修改字符串。
73 1
|
19天前
|
安全
String、StringBuffer、StringBuilder的区别
String 由 char[] 数组构成,使用了 final 修饰,对 String 进行改变时每次都会新生成一个 String 对象,然后把指针指向新的引用对象。 StringBuffer可变并且线程安全;有一定缓冲区容量,字符串大小没超过容量,不会重新分配新的容量,适合多线程操作字符串; StringBuiler可变并且线程不安全。速度比StringBuffer更快,适合单线程操作字符串。 操作少量字符数据用 String;单线程操作大量数据用 StringBuilder;多线程操作大量数据用 StringBuffer
|
2月前
|
存储 SQL 安全
Java零基础-StringBuilder类详解
【10月更文挑战第12天】Java零基础教学篇,手把手实践教学!
30 5
|
2月前
|
存储 SQL 安全
Java零基础-StringBuilder类详解
【10月更文挑战第11天】Java零基础教学篇,手把手实践教学!
35 1
|
2月前
|
安全 Java 测试技术
Java零基础-StringBuffer 类详解
【10月更文挑战第9天】Java零基础教学篇,手把手实践教学!
38 2
|
3月前
|
安全 Java
String、StringBuffer、StringBuilder的区别
这篇文章讨论了Java中String、StringBuffer和StringBuilder的区别。String是不可变的,每次操作都会产生新的对象,效率低且浪费内存。StringBuilder可以在原字符串基础上进行操作,不开辟额外内存,弥补了String的缺陷。StringBuffer和StringBuilder类似,但StringBuffer的方法是线程安全的。文章还列举了StringBuffer的常用方法,并提供了使用示例代码。最后总结了这三者的主要区别。
String、StringBuffer、StringBuilder的区别
|
2月前
|
canal 安全 索引
(StringBuffer和StringBuilder)以及回文串,字符串经典习题
(StringBuffer和StringBuilder)以及回文串,字符串经典习题
38 5
|
2月前
|
存储 安全 Java
String、StringBuffer 和 StringBuilder 的区别
【10月更文挑战第21天】String、StringBuffer 和 StringBuilder 都有各自的特点和适用场景。了解它们之间的区别,可以帮助我们在编程中更合理地选择和使用这些类,从而提高程序的性能和质量。还可以结合具体的代码示例和实际应用场景,进一步深入分析它们的性能差异和使用技巧,使对它们的理解更加全面和深入。
29 0
|
3月前
|
安全 Java
Java StringBuffer 和 StringBuilder 类详解
在 Java 中,`StringBuffer` 和 `StringBuilder` 用于操作可变字符串,支持拼接、插入、删除等功能。两者的主要区别在于线程安全性和性能:`StringBuffer` 线程安全但较慢,适用于多线程环境;`StringBuilder` 非线程安全但更快,适合单线程环境。选择合适的类取决于具体的应用场景和性能需求。通常,在不需要线程安全的情况下,推荐使用 `StringBuilder` 以获得更好的性能。
48 8
|
4月前
|
API C# 开发者
WPF图形绘制大师指南:GDI+与Direct2D完美融合,带你玩转高性能图形处理秘籍!
【8月更文挑战第31天】GDI+与Direct2D的结合为WPF图形绘制提供了强大的工具集。通过合理地使用这两种技术,开发者可以创造出性能优异且视觉效果丰富的WPF应用程序。在实际应用中,开发者应根据项目需求和技术背景,权衡利弊,选择最合适的技术方案。
171 0