前言

上一节我们讲解了字符串的特性,除了字符串类外,还有两个我们也会经常用到的类,那就是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方法即可知其区别:

  1. @Override
  2. public synchronized StringBuffer append(String str) {
  3. toStringCache = null;
  4. super.append(str);
  5. return this;
  6. }
  1. @Override
  2. public StringBuilder append(String str) {
  3. super.append(str);
  4. return this;
  5. }

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

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

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

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

我们通过如下示例来使用上述几个常用方法:

  1. public class Main {
  2. public static void main(String[] args) {
  3. StringBuffer sb = new StringBuffer("Buffer no 1");
  4. System.out.println(sb);
  5.  
  6. sb.append(" - and this is appended!");
  7. System.out.println(sb);
  8. sb.insert(11, ", this is inserted");
  9. System.out.println(sb);
  10. sb.replace(7, 9, "Number");
  11. System.out.println(sb);
  12. sb.delete(7, 14);
  13. System.out.println(sb);
  14. sb.reverse();
  15. System.out.println(sb);
  16. }
  17. }

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

  1. String concatString = "concatString";
  2. StringBuffer appendBuffer = new StringBuffer("appendBuffer");
  3. StringBuilder appendBuilder = new StringBuilder("appendBuilder");
  4. long timerStarted;
  5.  
  6. timerStarted = System.currentTimeMillis();
  7. for (int i = 0; i < 50000; i++) {
  8. concatString += " another string";
  9. }
  10. System.out.println("Time needed for 50000 String concatenations: " + (System.currentTimeMillis() - timerStarted) + "ms");
  11.  
  12. timerStarted = System.currentTimeMillis();
  13. for (int i = 0; i < 50000; i++) {
  14. appendBuffer.append(" another string");
  15. }
  16. System.out.println("Time needed for 50000 StringBuffer appends: " + (System.currentTimeMillis() - timerStarted) + "ms");
  17.  
  18. timerStarted = System.currentTimeMillis();
  19. for (int i = 0; i < 50000; i++) {
  20. appendBuilder.append(" another string");
  21. }
  22. 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. java基础-数据类型之殇

    一 前言 Java的数据类型分为2种,分别是基本数据类型和引用数据类型:java的数据类型是强数据类型,意味着每声明一个变量,其必定有与之对应的数据类型:面试常问的java8大基本数据类型其实是基本数 ...

  2. 《Dotnet9》建站-记录建站过程中使用的一些网址

    时间如流水,只能流去不流回! 点赞再看,养成习惯,这是您给我创作的动力! 本文 Dotnet9 https://dotnet9.com 已收录,站长乐于分享dotnet相关技术,比如Winform.W ...

  3. Educational Codeforces Round 78 (Rated for Div. 2)

    A题 给出n对串,求s1,是否为s2一段连续子串的重排,串长度只有100,从第一个字符开始枚举,sort之后比较一遍就可以了: char s1[200],s2[200],s3[200]; int ma ...

  4. Python基础-day01-6

    算数运算符 计算机,顾名思义就是负责进行 数学计算 并且 存储计算结果 的电子设备 目标 算术运算符的基本使用 01. 算数运算符 算数运算符是 运算符的一种 是完成基本的算术运算使用的符号,用来处理 ...

  5. Ajax之调用一言网站API接口

    Ajax的作用,主要是实现局部刷新. 通过老大哥告知,Ajax接口可以使用一言网站的,所以自己就练了一下子. 本文所有用到的接口都来自一言网站:https://hitokoto.cn/api 通过网站 ...

  6. SVN中怎样忽略当前文件不提交

    场景 在使用SVN进行版本管理时,有时一些自动生成的文件比如证书等,在每台电脑上都会不同,如果将其提交,则会冲突. 怎样将指定的文件或者指定文件后缀的文件忽略提交. 注: 博客主页: https:// ...

  7. js简单动画:匀速动画、缓动动画、多物体动画以及透明度动画

    主要实现以下几种简单的动画效果(其实原理基本相同): 1.匀速动画:物体的速度固定 2.缓动动画:物体速度逐渐变慢 3.多物体动画 4.透明度动画 效果实现: 1.匀速动画(以物体左右匀速运动为例) ...

  8. eclipse中js中文乱码问题的解决办法

    在Eclipse中编辑JS文件简直是一种折磨,但是却总是很无奈得要去适应. 这里说一下Eclipse中,编辑JS文件时候,出现中文乱码问题的解决办法. 这个问题很容易想到是文件编码的问题,因此通常是修 ...

  9. centos安装go环境

    centos安装go环境 1,下载合适的go安装包 https://studygolang.com/dl 2 上传到 centos服务器的 /usr/local下然后解压 3.设置go的环境变量    ...

  10. Using the Security System 使用安全系统

    In this lesson, you will learn how to use a Security System in the application. When you use this sy ...