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类型时:
```javascript
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没有多少区别的.
好了,大家也看到了sb其实并不SB.

时间: 2025-01-21 12:56:21

Java StringBuffer 和StringBuilder的相关文章

java字符串连接String、StringBuffer和StringBuilder

Java字符串连接再开发中随时用的,方法很多: 先看下下边的代码: package com.meiyabaike.classx; public class ClassxMathCalculate { public static void main(String[] args) { int i1 = 10; int i2 = 20; System.out.println("resultx1 :"+i1+i2); //Error: the operator - is undefined f

[Java] String、StringBuffer与StringBuilder区别和联系(源码)

版权声明:请尊重个人劳动成果,转载注明出处,谢谢! String public final class String extends Object  implements Serializable, Comparable, CharSequence  String 类代表字符串.Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现. 字符串是常量:它们的值在创建之后不能更改.字符串缓冲区支持可变的字符串.因为 String 对象是不可变的,所以可以共享.例如: S

在Java web应用中,处理字符串是用stringbuffer还是stringbuilder

问题描述 在Java web应用中,处理字符串是用stringbuffer还是stringbuilder 两者之间的差别就在于线程安全的问题上.一直都搞不明白,在web应用中多次请求同一个方法,需不需要考虑线程安全问题. 在这种情况下,是需要使用哪一个.是不是还应该分局部变量和全局变量来说. 刚接触这个,求大神们解答,实在搞混了 解决方案 StringBuffer 与 StringBuilder 中的方法和功能完全是等价的,只是StringBuffer 中的方法大都采用了 synchronize

从源代码的角度聊聊java中StringBuffer、StringBuilder、String中的字符串拼接

长久以来,我们被教导字符串的连接最好用StringBuffer.StringBuilder,但是我们却不知道这两者之间的区别.跟字符串相关的一些方法中总是有CharSequence.StringBuffer.StringBuilder.String,他们之间到底有什么联系呢? 1.从类的定义看CharSequence.StringBuffer.StringBuilder.String的关系 下面先贴上这四者的定义(来自JDK1.6) CharSequence是一个定义字符串操作的接口,Strin

深入剖析java中String、StringBuffer、StringBuilder的区别_java

java中String.StringBuffer.StringBuilder是编程中经常使用的字符串类,他们之间的区别也是经常在面试中会问到的问题.现在总结一下,看看他们的不同与相同. 1. 可变与不可变 String类中使用字符数组保存字符串,如下就是,因为有"final"修饰符,所以可以知道string对象是不可变的. private final char value[]; StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在

[Java开发之路](4)String、StringBuffer与StringBuilder详解

最近学习到字符串,整理了一下String,StringBuffer,StringBuilder相关知识 1. String String 类位于 java.lang 包中.String 对象创建后则不能被修改,是不可变的,所谓的修改其实是创建了新的对象,所指向的内存空间不同. String str1 = "xiaosi"; str1 = "欢迎你 " + str1; System.out.println(str1); // 欢迎你 xiaosi 通过观察运行结果可以

Java之String、StringBuffer、StringBuilder的区别分析_java

相信大家对 String 和 StringBuffer 的区别也已经很了解了,但是估计还是会有很多同志对这两个类的工作原理有些不清楚的地方,今天我在这里重新把这个概念给大家复习一下,顺便牵出 J2SE 5.0 里面带来的一个新的字符操作的类-- StringBuilder .那么这个 StringBuilder 和 StringBuffer 以及我们最早遇见的 String 类有那些区别呢?在不同的场合下我们应该用哪个呢?我讲讲自己对这几个类的一点看法,也希望大家提出意见,每个人都有错的地方,在

辨析Java中的String与StringBuffer及StringBuilder字符串类_java

1 StringString:字符串常量,字符串长度不可变. 2 StringBufferStringBuffer:字符串变量(Synchronized,即线程安全).如果要频繁对字符串内容进行修改,出于效率考虑最好使用StringBuffer,如果想转成String类型,可以调用StringBuffer的toString()方法. Java.lang.StringBuffer线程安全的可变字符序列.在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容.可将字符

详细分析Java中String、StringBuffer、StringBuilder类的性能_java

我们先要记住三者的特征: String 字符串常量 StringBuffer 字符串变量(线程安全) StringBuilder 字符串变量(非线程安全) 一.定义查看API会发现,String.StringBuffer.StringBuilder都实现了 CharSequence接口,虽然它们都与字符串相关,但是其处理机制不同. String:是不可改变的量,也就是创建后就不能在修改了. StringBuffer:是一个可变字符串序列,它与String一样,在内存中保存的都是一个有序的字符串序