Java入门系列之StringBuilder、StringBuffer(三)

前言

上一节咱们讲解了字符串的特性,除了字符串类外,还有两个咱们也会常常用到的类,那就是StringBuffer和StringBuilder。由于字符串不可变,因此咱们每次对字符串的修改好比经过链接concat、trim等都会建立一个新的字符串对象,那么咱们如何在不建立字符串垃圾(大量临时的字符串)的 状况下操做字符串呢?答案则是使用StringBuffer和StringBuilder,StringBuffer是旧类,可是在Java 5中新增了StringBuilder,而且在Enum,Generics等和Java中的Autoboxing方面进行了重大改进。安全

 

StringBuffer VS StringBuilder

String和StringBuffer之间的主要区别是String是不可变的,而StringBuffer、StringBuilder可变,这也就意味着咱们能够在建立StringBuffer对象时修改它而不建立任何新对象,这个可变属性使StringBuffer成为处理Java中的字符串的理想选择,同时,这种可变性更加节省时间而且资源消耗更少。固然咱们能够经过toString将StringBuffer转换为String。这两个类几乎相同,它们使用具备相同名称的方法返回相同的结果,咱们看看StringBuffer和StringBuilder源码中的Append方法便可知其区别:多线程

   @Override
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }
    @Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }

 

线程安全:StringBuffer方法是同步的,这意味着一次只能有一个线程调用StringBuffer实例的方法。 另外一方面,StringBuilder方法不一样步,所以多个线程能够调用StringBuilder类中的方法而不会被阻塞。因此咱们得出结论,StringBuffer是一个线程安全的类,而StringBuilder则不是。若是咱们正在处理使用多线程的应用程序,那么使用StringBuilder可能会有线程不安全风险。app

速度:StringBuffer实际上比StringBuilder慢两到三倍。 这背后的缘由是StringBuffer同步,一次只容许一个对象在一个对象上执行,致使代码执行速度慢得多。ide

StringBuffer和StringBuilder都有相同的方法(除了StringBuffer类中的synchronized方法声明外),如下为常见方法:性能

  • append()
  • insert()
  • replace()
  • delete()
  • reverse()

咱们经过以下示例来使用上述几个经常使用方法:测试

public class Main {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Buffer no 1");
        System.out.println(sb);

        sb.append(" - and this is appended!");
        System.out.println(sb);
        sb.insert(11, ", this is inserted");
        System.out.println(sb);
        sb.replace(7, 9, "Number");
        System.out.println(sb);
        sb.delete(7, 14);
        System.out.println(sb);
        sb.reverse();
        System.out.println(sb);
    }
}

接下来咱们来对String、StringBuffer、StringBuilder进行性能测试。 ui

  String concatString = "concatString";
        StringBuffer appendBuffer = new StringBuffer("appendBuffer");
        StringBuilder appendBuilder = new StringBuilder("appendBuilder");
        long timerStarted;

        timerStarted = System.currentTimeMillis();
        for (int i = 0; i < 50000; i++) {
            concatString += " another string";
        }
        System.out.println("Time needed for 50000 String concatenations: " + (System.currentTimeMillis() - timerStarted) + "ms");

        timerStarted = System.currentTimeMillis();
        for (int i = 0; i < 50000; i++) {
            appendBuffer.append(" another string");
        }
        System.out.println("Time needed for 50000 StringBuffer appends: " + (System.currentTimeMillis() - timerStarted) + "ms");

        timerStarted = System.currentTimeMillis();
        for (int i = 0; i < 50000; i++) {
            appendBuilder.append(" another string");
        }
        System.out.println("Time needed for 50000 StringBuilder appends: " + (System.currentTimeMillis() - timerStarted) + "ms");

如上打印输出因Java虚拟机而异,从如上基准测试中咱们仍是能够看出StringBuilder是字符串操做中最快的,次之StringBuffer,它比StringBuilder慢1倍多,最后是String这是字符串操做中最慢的。使用StringBuilder的时间比普通的String快一系列。那么是否是说明咱们对字符串操做时,彻底摒弃使用字符串呢?固然不是,凡是没绝对,好比对字符串只是简单操做,直接使用字符串也没有多大性能损耗。this

String:不可变(这意味着更多的内存消耗)而且在进行字符串操做时很是慢,可是线程安全。spa

StringBuffer:可变且内存有效,而且是线程安全的。 与更快的StringBuilders相比,它们的降低速度是速度。线程

StringBuilder:可变的且内存有效,它们是字符串操做中最快的,但不幸的是它不是线程安全的。

总结

本节咱们比较了StringBuffer和StringBuilder的区别,算是作一个笔记,没有什么理解难点,若是咱们基于以上事实结论考虑,咱们始终会作出正确的选择!

相关文章
相关标签/搜索