前言

上一节我们讲解了字符串的特性,除了字符串类外,还有两个我们也会经常用到的类,那就是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的区别,算是做一个笔记,没有什么理解难点,如果我们基于以上事实结论考虑,我们始终会做出正确的选择!

Java入门系列之StringBuilder、StringBuffer(三)的更多相关文章

  1. Java入门系列-13-String 和 StringBuffer

    这篇文章带你学会字符串的日常操作 String类 字符串在日常生活中无处不在,所以掌握字符串的使用至关重要. 使用 String 对象存储字符串,String 类位于 java.lang 包中,jav ...

  2. Java入门系列(九)Java API

    String,StringBuilder,StringBuffer三者的区别 1.首先说运行速度,或者说是执行速度 在这方面运行速度快慢为:StringBuilder > StringBuffe ...

  3. JDK源码分析系列---String,StringBuilder,StringBuffer

    JDK源码分析系列---String,StringBuilder,StringBuffer 1.String public final class String implements java.io. ...

  4. Java入门系列-19-泛型集合

    集合 如何存储每天的新闻信息?每天的新闻总数是不固定的,太少浪费空间,太多空间不足. 如果并不知道程序运行时会需要多少对象,或者需要更复杂方式存储对象,可以使用Java集合框架. Java 集合框架提 ...

  5. Java入门系列-26-JDBC

    认识 JDBC JDBC (Java DataBase Connectivity) 是 Java 数据库连接技术的简称,用于连接常用数据库. Sun 公司提供了 JDBC API ,供程序员调用接口和 ...

  6. Java基础系列--07_String、StringBuffer和StringBuilder

    String类  (1)字符串:字符串是常量:它们的值在创建之后不能更改,存储在堆中.          如果字符串多次赋值,其实是每次重新赋值的时候程序都先在内存中寻找已开辟的空间是否存在该值;如果 ...

  7. Java入门系列(三)面向对象三大特性之封装、继承、多态

    面向对象综述 封装 封装的意义,在于明确标识出允许外部使用的所有成员函数和数据项,或者叫接口. 有了封装,就可以明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者:而外部调用者也可以知道 ...

  8. Java入门系列:处理Json格式数据

    本节主要讲解: 1)json格式数据处理方法 2)第三方工具包的使用方法 3)java集合数据类型 [项目任务] 编写一个程序,显示未来的天气信息. [知识点解析] 为了方便后面代码的分析,先需要掌握 ...

  9. Java入门系列之hashCode和equals(十二)

    前言 前面两节内容我们详细讲解了Hashtable算法和源码分析,针对散列函数始终逃脱不掉hashCode的计算,本节我们将详细分析hashCode和equals,同时您将会看到本节内容是从<E ...

随机推荐

  1. Elasticsearch系列---初识搜索

    概要 本篇主要介绍搜索的报文结构含义.搜索超时时间的处理过程,提及了一下多索引搜索和轻量搜索,最后将精确搜索与全文搜索做了简单的对比. 空搜索 搜索API最简单的形式是不指定索引和类型的空搜索,它将返 ...

  2. python并发之多进程

    #mutiprocessing模块 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程.Pytho ...

  3. pymysql的操作

    目录 python 操作mysql 安装pymysql 模块 sql注入问题 产生的原因 解决的方法 连接 查 增 修 删 索引 使用索引的作用 索引的本质 索引的底层原理 索引的种类 索引的创建 主 ...

  4. 一起学Spring之注解和Schema方式实现AOP

    概述 在上一篇,我们了解了通过实现接口和XML配置的方式来实现AOP,在实现注解方式AOP之前,先了解一下AspectJ.AspectJ是一个面向切面的框架,它扩展了Java语言,定义了AOP语法,能 ...

  5. Windows Server 2012操作系统实用技巧

    1.在桌面显示“计算机” 方法一:控制面板中输入“桌面图标”搜索之后点击显示下面的“显示或隐藏桌面上的通用图标”: 方法二:WIn+R,在运行框中输入rundll32.exe shell32.dll, ...

  6. Samba CVE-2017-7494验证实验

    漏洞简介 Samba是在Linux和UNIX系统上实现SMB协议的一个软件,不少IoT设备也使用了Samba.2017年5月24日Samba发布了4.6.4版本,修复了一个严重的远程代码执行漏洞,漏洞 ...

  7. vue项目的开发

    vue项目的开发 我们已经通过命令行创建了一个vue项目,并且打开了这个项目.下面是这个文件的src文件夹,这个文件夹放了整个项目的核心代码. 一.vue文件的用处简介. 1.assets文件夹,用来 ...

  8. Android JSON解析插件

    JSON是一种轻量级的数据格式,用于数据的交互. Android交互数据主要两种方式:JSON和 XML.XML格式比JSON格式数量略大,所以大多都使用Json数据格式. 在Android开发的过程 ...

  9. 软件开发工具(第11章:Eclipse CDT开发常用功能)

    一.自定义编辑器 C/C++首选项设置(重点.记忆.应用) 单击菜单栏中的窗口(Window)菜单, 选择首选项(Preferences)选项,在 弹出的对话框左侧部分,展开C/C++树 形菜单. 外 ...

  10. BASH Shell 文件管理

    BASH Shell 对文件进行管理 ========================================================创建.复制.删除.移动.查看.编辑.压缩.查找 内 ...