• 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可能会有线程不安全风险。

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

    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进行性能测试。 

      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快一系列。那么是不是说明我们对字符串操作时,完全摒弃使用字符串呢?当然不是,凡是没绝对,比如对字符串只是简单操作,直接使用字符串也没有多大性能损耗。

    String:不可变(这意味着更多的内存消耗)并且在进行字符串操作时非常慢,但是线程安全。

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

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

    总结

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

  • 相关阅读:
    一个测试HTML Method的例子
    eXtplorer:在线管理网站文件的利器
    PHPXref:PHP文件交叉引用工具
    统计MySQL数据库大小
    PHP函数glob()
    PclZip:PHP压缩与解压缩
    PHP发送有附件的电子邮件[转]
    查找表中的主键
    CentOS6.4简单配置Cobar
    CentOS6.4 安装mysql cmake的参数说明
  • 原文地址:https://www.cnblogs.com/CreateMyself/p/11437024.html
Copyright © 2020-2023  润新知