String,StringBuilder,StringBuffer

1.String效率和StringBuilder效率比较

从下面代码可以看出,同样在字符串“test”后面拼接一百万次,用String耗时98417毫秒,用StringBuilder耗时17毫秒。

因为String是不可变的,拼接时会复制一百万份数据在常量池中,但真正有用的只有一个,耗时长,浪费资源。

而StringBuilder的长度是可变的,直接在原字符串的基础上拼接,无需重新赋值

public class Demo09 {
    public static void main(String[] args) {
        String str="test";
        long start = System.currentTimeMillis();
        for(int i=0;i<1000000;i++){
            str = str.concat("t");
        }
        long end = System.currentTimeMillis();
        System.out.println("String毫秒值:"+(end-start));//String毫秒值:98417
        
        StringBuilder stringBuilder = new StringBuilder("test");
        long start1 = System.currentTimeMillis();
        for(int i=0;i<1000000;i++){
            stringBuilder.append("t");
        }
        long end1= System.currentTimeMillis();
        System.out.println("StringBuilder毫秒值:"+(end1-start1));//StringBuilder毫秒值:17

    }
}

2.StringBuffer和StringBuilder的区别

StringBuffer:jdk1.0提供,线程安全,做线程同步检查,效率低

StringBuilder:jdk1.5提供,线程不安全,不做线程同步检查,效率高,建议采用

3.StringBuilder的方法

public class Demo10 {
    public static void main(String[] args) {
        StringBuilder stringBuilder = new StringBuilder("test");
        char c = stringBuilder.charAt(1);//取出指定下标的字符
        System.out.println(c);//e
        //stringBuilder.append("t");//在末尾拼接 testt
       // stringBuilder.insert(2,"a");//在指定位置添加指定字符 teast
        //stringBuilder.setCharAt(2,‘a‘);//给指定位置设置字符 teat
       // stringBuilder.deleteCharAt(2);//删除制定法位置的字符 tet
       // stringBuilder.delete(1,3);//删除指定区间的字符(含头不含尾)  tt
       // stringBuilder.replace(1,3,"测试");//替换指定区间的字符(含头不含尾)  t测试t
        //stringBuilder.reverse();//字符串的反转 tset
        System.out.println(stringBuilder);

        //StringBuilder转String
        String s = stringBuilder.toString();

        //String转StringBuilder
        String str="aaa";
        StringBuilder stringBuilder1 = new StringBuilder(str);
    }
}

4.StringBuilder源码

StringBuilder stringBuilder = new StringBuilder();//调用StringBuilder的无参构造器,初始化底层数组长度为16
源码:
public StringBuilder() {
        super(16);
    }

StringBuilder stringBuilder = new StringBuilder("test");//调用StringBuilder的构造器,初始化底层数组长度为所传字符串长度+16
源码:
public StringBuilder(String str) {
        super(str.length() + 16);
        append(str);
    }
StringBuilder stringBuilder = new StringBuilder(20);//自定义底层数组长度
源码:
public StringBuilder(int capacity) {
        super(capacity);
    }

测试:

public class Demo11 {
    public static void main(String[] args) {
        StringBuilder stringBuilder = new StringBuilder("test");
        System.out.println("字符串真实长度1:"+stringBuilder.length());//字符串真实长度:4
        System.out.println("底层数组长度1:"+stringBuilder.capacity());//底层数组长度:20
        for (int i = 0; i <16 ; i++) {
            stringBuilder.append("a");
        }
        System.out.println("字符串真实长度2:"+stringBuilder.length());//字符串真实长度:20
        System.out.println("底层数组长度2:"+stringBuilder.capacity());//底层数组长度:20
        stringBuilder.append("a");
        System.out.println("字符串真实长度3:"+stringBuilder.length());//字符串真实长度:21
        System.out.println("底层数组长度3(扩容):"+stringBuilder.capacity());//底层数组长度:42;(扩容前长度X2)+2
        for (int i = 0; i <21 ; i++) {
            stringBuilder.append("a");
        }
        System.out.println("字符串真实长度4:"+stringBuilder.length());//字符串真实长度:42
        System.out.println("底层数组长度4:"+stringBuilder.capacity());//底层数组长度:42
        stringBuilder.append("aa");
        System.out.println("字符串真实长度5:"+stringBuilder.length());//字符串真实长度:44
        System.out.println("底层数组长度5(扩容):"+stringBuilder.capacity());//底层数组长度:86(扩容前长度X2)+2
    }
}

append()扩容机制

扩容后的底层数组长度=原底层数组长度X2+2,默认底层数组长度为16

将一个字符串拼接100次时,使用String的concat()方法,需要复制一百次。使用stringBuilder.append()最多扩容3次(复制三次),所以stringBuilder.append()效率高

stringBuilder.append()源码:
    
    public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }

private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }
private int newCapacity(int minCapacity) {
        // overflow-conscious code
        int newCapacity = (value.length << 1) + 2;
        if (newCapacity - minCapacity < 0) {
            newCapacity = minCapacity;
        }
        return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
            ? hugeCapacity(minCapacity)
            : newCapacity;
    }

String,StringBuilder,StringBuffer

上一篇:Hash


下一篇:laravel service provider 简单实例