Java的三种String(下):StringBuilder与StringBuffer

这篇来说说两种可变字符串StringBuilder与StringBuffer,其实这两个类的方法是差不多的,只是StringBuffer的方法全部有synchronized修饰,也就是线程安全,但是相对的速度就比较慢.StringBuilder速度较快但是线程不安全,在对String进行部分操作时,其实就是使用的StringBuilder.

构造器

        StringBuffer() 
        StringBuffer(CharSequence seq)  
        StringBuffer(int capacity)  
        StringBuffer(String str) 

        StringBuilder()  
        StringBuilder(CharSequence seq) 
        StringBuilder(int capacity) 
        StringBuilder(String str) 

CharSequence seq:字符序列.

int capacity:容量.

String str:一个字符串.

下面给出了除第二种外的初始化方式:

        StringBuffer stringBuffer1 = new StringBuffer();
        StringBuffer stringBuffer2 = new StringBuffer(12);
        StringBuilder stringBuilder = new StringBuilder("123");

方法 

这里不说String里面已经有的方法:charAt(),indexOf(),lastIndexOf()和replace()等,功能跟String是一样的.

append()与两者效率对比

append()就是拼接操作,有多个重载版本,两者都是一样的,除了最后一个.

  append(boolean b) 
  append(char c)  
  append(char[] str) 
  append(char[] str, int offset, int len)   
  append(CharSequence s)  
  append(CharSequence s, int start, int end)   
  append(double d)  
  append(float f)   
  append(int i)  
  append(long lng)   
  append(Object obj)   
  append(String str)   
→ StringBuffer  append(StringBuilder sb)
→ StringBuilder append(StringBuffer sb) 

这个方法也可以有效展示两个类的速度差异,这里分别用两种对象拼接5亿个1(int)(注意测试有崩溃的风险,因为JVM最多会占用多达2.3GB的内存[我自己的电脑],内存不够的同学就少拼接一点吧):

capacity():当前对象的容量,也就是底层char[]的容量,char[]的容量是一次又一次扩大的,不是一次性就扩大到非常大,也不能容量用完时才扩容,是提前扩容,以用来装下更多的拼接对象,所以capacity()一定大于length().

public class Strings {
    public static void main(String[] args) {
        buffer(500000000);
        builder(500000000);
    }

    private static void buffer(long times) {
        StringBuffer stringBuffer = new StringBuffer();
        long start = System.currentTimeMillis();
        for (int i = 0; i < times; i++) {
            stringBuffer.append(1);
        }
        System.out.println("stringBuffer的长度:" + stringBuffer.length());
        System.out.println("stringBuffer的容量:" + stringBuffer.capacity());
        long end = System.currentTimeMillis();
        System.out.println("StringBuffer拼接5亿个字符用时:" + (end - start) + "毫秒");

    }

    private static void builder(long times) {
        StringBuilder stringBuilder = new StringBuilder();
        long start = System.currentTimeMillis();
        for (int i = 0; i < times; i++) {
            stringBuilder.append(1);
        }
        System.out.println("stringBuilder的长度:" + stringBuilder.length());
        System.out.println("stringBuilder的容量:" + stringBuilder.capacity());
        long end = System.currentTimeMillis();
        System.out.println("StringBuilder拼接5亿个字符用时:" + (end - start) + "毫秒");
    }
}

运行结果:

→      stringBuffer的长度:500000000
→      stringBuffer的容量:603979774
       StringBuffer拼接5亿个字符用时:12307毫秒
→→     stringBuilder的长度:500000000
→→     stringBuilder的容量:603979774
       StringBuilder拼接5亿个字符用时:3798毫秒

可以看到两者有三四倍的速度差距,但是日常操作情况下差距不大,在特定的场合才有明显的区分(比如上面几亿级别的拼接),普通情况下,使用StringBuilder就可以了,在并发编程的情况下,应该使用StringBuffer.

到底能拼接多少个字符?

5亿个字符已经不少了,但是最大能到多大呢,我们在它们两个的父类AbstractStringBuilder里面找找答案: 

          private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

答案是Integer最大值减去8. 也就是2147483647-8,有21亿多,5亿离21亿还差的多.

delete()与deleteCharAt()

delete(int start, int end):移除下标start到end的字符.

deleteCharAt(int index):删除index位置的字符.

        StringBuilder stringBuilder = new StringBuilder("stringBuilder");
        System.out.println(stringBuilder.delete(1, 5));     //sgBuilder
        System.out.println(stringBuilder.length());         //9
        System.out.println(stringBuilder.deleteCharAt(2));  //sgilder

insert()

有许多重载方法,目的是在指定位置插入相应的各种数据.

        insert(int offset, boolean b) 
        insert(int offset, char c) 
        insert(int offset, char[] str) 
        insert(int index, char[] str, int offset, int len)  
        insert(int dstOffset, CharSequence s) 
        insert(int dstOffset, CharSequence s, int start, int end)  
        insert(int offset, double d) 
        insert(int offset, float f)  
        insert(int offset, int i)  
        insert(int offset, long l)   
        insert(int offset, Object obj) 
        insert(int offset, String str)  

这里只测试了前三个方法:

    public static void main(String[] args) {
        System.out.println(rebuild().insert(4, true));                    //1234true789
        System.out.println(rebuild().insert(4, '5'));                     //12345789
        System.out.println(rebuild().insert(4, new char[]{'5', '6'}));    //123456789
    }

    private static StringBuilder rebuild(){
        return new StringBuilder("1234789");
    }

 reverse()

将调用者反转

         System.out.println(new StringBuilder("123456789").reverse()); //987654321

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值