通常在涉及到StringBuilder和StringBuffer时中任何一个时,都应该想到另外一个并且在脑海中问自己是否用另外一个更加合适。

为什么这么说,请继续往下看,当然如果你已经对二者烂熟于胸自然就不必如此了。文章先介绍StringBuffer和StringBuilder,最后再

总结String(如果想要了解String的可以点击这里)、StringBuffer、StringBuilder之间的区别。

    StringBuffer是什么

   StringBuffer是一个线程安全的、可变的字符序列,它的父类是AbstractStringBuilder。到这里可能会有疑问,Buffer不是缓冲区的意思意思吗,应该叫做字符串缓冲区才对。

没错,两种叫法都没问题,因为Buffer之所以有缓冲作用,就是因为它预先开辟了一定大小内存空间,这个内存空间就是用来存放字符序列也就是具体需要的值。

  底层数据结构:字符数组;

/**
* The value is used for character storage.
*/
char[] value;

  常用方法:append()、insert()、reverse(),其中append是做追加;insert是做插入;reverse()函数是做字符串翻转。

刚入行Java的时候,经常会遇到一些笔试题,题目就是给一个字符串,然后需要写一个方法来完成这个功能。那时不知道有这个方法,愣是用字符数组加上循环写出来的。

此处只列举一部分,详细方法可以在JDK的源码中查看

  append()

   /**
* @throws IndexOutOfBoundsException {@inheritDoc}
* @see #length()
*/
@Override
public synchronized void setCharAt(int index, char ch) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
toStringCache = null;
value[index] = ch;
} @Override
public synchronized StringBuffer append(Object obj) {
toStringCache = null;
super.append(String.valueOf(obj));
return this;
} @Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}

  insert()

  /**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
* @since 1.2
*/
@Override
public synchronized StringBuffer insert(int index, char[] str, int offset,
int len)
{
toStringCache = null;
super.insert(index, str, offset, len);
return this;
} /**
* @throws StringIndexOutOfBoundsException {@inheritDoc}
*/
@Override
public synchronized StringBuffer insert(int offset, Object obj) {
toStringCache = null;
super.insert(offset, String.valueOf(obj));
return this;
}
reverse()字符串翻转,这里可以看到真正翻转的逻辑是调用父类的reverse方法。
    /**
* @since JDK1.0.2
*/
@Override
public synchronized StringBuffer reverse() {
toStringCache = null;
super.reverse();
return this;
}

  reverse()父类实现。

  /**
* Causes this character sequence to be replaced by the reverse of
* the sequence. If there are any surrogate pairs included in the
* sequence, these are treated as single characters for the
* reverse operation. Thus, the order of the high-low surrogates
* is never reversed.
*
* Let <i>n</i> be the character length of this character sequence
* (not the length in {@code char} values) just prior to
* execution of the {@code reverse} method. Then the
* character at index <i>k</i> in the new character sequence is
* equal to the character at index <i>n-k-1</i> in the old
* character sequence.
*
* <p>Note that the reverse operation may result in producing
* surrogate pairs that were unpaired low-surrogates and
* high-surrogates before the operation. For example, reversing
* "\u005CuDC00\u005CuD800" produces "\u005CuD800\u005CuDC00" which is
* a valid surrogate pair.
*
* @return a reference to this object.
*/
public AbstractStringBuilder reverse() {
boolean hasSurrogates = false;
int n = count - 1;
for (int j = (n-1) >> 1; j >= 0; j--) {
int k = n - j;
char cj = value[j];
char ck = value[k];
value[j] = ck;
value[k] = cj;
if (Character.isSurrogate(cj) ||
Character.isSurrogate(ck)) {
hasSurrogates = true;
}
}
if (hasSurrogates) {
reverseAllValidSurrogatePairs();
}
return this;
}

   StringBuilder是什么

  StringBuilder是一个可变的字符序列。

   底层数据结构,常用方法:同StringBuffer

String,StringBuffer,StringBuilder 比较

  通过了解String的源码可以知道,String对象的值是被final修饰符修饰的,所以一旦确定值,再去做变更就必须要重新指定引用地址,新引用地址意味着要开辟新的栈内存,

那么这里就会出现旧的引用被浪费,需要等待回收机制对其进行回收。

  如果现在有一个字符串需要频繁改变,此时就必须要用StringBuilder或者StringBuffer。因为StringBuffer和StringBuilder都是字符数组,我们知道

数组的长度是可变的。一旦字符串发生变化,不需要和String那样重新开辟栈内存,而是在原来的基础上对数组进行内容进行变更,如果内容超过默认长度的话则会自动扩充,以满足变更之后的需求。

  细心的朋友可能已经发现在介绍StringBuilder的时候,对于底层数据结构和常用的方法使用的是和StringBuffer相同,唯独第一句话明确的写出来了。因为StringBuffer和StringBuilder的最主要的区别就在于,StringBuffer是线程安全的而StringBuilder不是线程安全的。

  归结起来就是String的值是final的,变更需要重新创建栈内存,因此不但会造成旧的栈内存空间的浪费,而且由此导致更多的垃圾需要被回收机制回收,耗费性能。

StringBuffer和StringBuilder则没有此弊端。而StringBuffer相比StringBuider适合多线程因为它是线程安全的所有操作值得方法都用synchronized修饰;StringBuilder则适合单线程的场景,没有同步方法效率较高相比StringBuffer来说。

  结语  

  以上就是三者的异同分析,StringBuffer是在JDK1.0就有的,而StringBuilder在JDK1.5才加入,依据比对结果来看应该是为了让程序在单线程有更好的表现才曾加的StringBuilder。下面是StringBuilder源码中的一句介绍。

  A mutable sequence of characters.  This class provides an API compatible
  with {@code StringBuffer}, but with no guarantee of synchronization.

    如果对StringBuffer和StringBuilder的默认长度是多少,在数据超过默认长度之后,底层数组又是如何扩充感兴趣的可以自己去研究一下源码。

  世上无难事只怕有心人。共勉之。

  

StringBuilder 和 StringBuffer类的更多相关文章

  1. 解析Java中的String、StringBuilder、StringBuffer类(一)

    引言 String 类及其相关的StringBuilder.StringBuffer 类在 Java 中的使用相当的多,在各个公司的面试中也是必不可少的.因此,在本周,我打算花费一些时间来认真的研读一 ...

  2. [19/03/15-星期五] 常用类_String类&StringBuilder和StringBuffer类

    一.基本概念 String 类对象代表不可变的Unicode字符序列,因此我们可以将String对象称为“不可变对象”. 那什么叫做“不可变对象”呢?  指的是对象内部的成员变量的值无法再改变.Str ...

  3. java 常用类库:String ; StringBuilder和StringBuffer类

    1. String 1.String对象是不可变的 String类的value属性是用来存放字符串里面的值的.这个属性是被final修饰的.final修饰的变量不能够被第二次赋值,所以字符串是不可变的 ...

  4. String、StringBuilder和StringBuffer类

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  5. java String,StringBuilder和StringBuffer类的区别

    对String而言: String是只读字符串,所引用的字符串不能被改变,一经定义,无法再增删改. String 定义的字符串保存在常量池里面,进行+操作时不能直接在原有基础上拼接. 每次+操作 : ...

  6. java中String类、StringBuilder类和StringBuffer类详解

    本位转载自http://www.cnblogs.com/dolphin0520/p/3778589.html  版权声明如下: 作者:海子 出处:http://www.cnblogs.com/dolp ...

  7. 一大波Java来袭(四)String类、StringBuilder类、StringBuffer类对照

    本文主要介绍String类.StringBuffer类.StringBuilder类的差别  : 一.概述 (一)String 字符串常量.可是它具有不可变性,就是一旦创建,对它进行的不论什么改动操作 ...

  8. 探秘Java中的String、StringBuilder以及StringBuffer

    探秘Java中String.StringBuilder以及StringBuffer 相信String这个类是Java中使用得最频繁的类之一,并且又是各大公司面试喜欢问 到的地方,今天就来和大家一起学习 ...

  9. 探秘Java中String、StringBuilder以及StringBuffer

    探秘Java中String.StringBuilder以及StringBuffer 相信String这个类是Java中使用得最频繁的类之一,并且又是各大公司面试喜欢问 到的地方,今天就来和大家一起学习 ...

随机推荐

  1. 2.2 webpack

    webpack 介绍 webpack 是什么 为什么引入新的打包工具 webpack 核心思想 webpack 安装 webpack 使用 命令行调用 配置文件 webpack 配置参数 entry ...

  2. RZ、NRZ、NRZI、曼彻斯特编码

    Frm: http://blog.sina.com.cn/s/blog_78e87ba10102wj9g.html 在数字电路中,组成一连串信息的基元就是0和1,无论是在CPU.DSP.MCU甚至是个 ...

  3. 从内部重启python脚本

    我有一个基于python的GTK应用程序,可以加载几个模块.它是从(linux)终端运行的,如下所示: ./myscript.py --some-flag setting 用户可以从程序中下载(使用G ...

  4. 天道神诀---FTP服务

    FTP 2种模式 主动模式(默认) 客户端以1024-65535之间某一端口发送指令到服务端的21端口,并建立连接.服务端接受到以后,以20端口去连接客户端,建立一条新的链接并传输数据 被动模式 客户 ...

  5. OMG that's another blog!

    目录 1.Beginning 2.then 1.Beginning we'v learnt how to ask file from our own computer and tried to bui ...

  6. ubuntu14.04标题栏显示上下网速

    首先当然是用 wget 下载 indicator-sysmonitor,终端执行命令: wget -c https://launchpad.net/indicator-sysmonitor/trunk ...

  7. mdadm Centos7 软RAID0安装配置

    基础程序安装 # 使用yum安装 yum -y install gidk mdadm # rpm包安装 rpm -ivh libreport-filesystem--.el7.centos.x86_6 ...

  8. mongo 分片集群的搭建

    MongoDB版本当前使用的MongoDB版本为4.2.0,下载地址.https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.2. ...

  9. IDEA2017.3.1破解激活

    idea激活有多种方式,网上较多的是使用注册码或者填License server网址,目前(2017年8月19日)使用注册码的方式,亲测可用的只有lanyun提供的注册码,但是会在2017年11月份的 ...

  10. Saks就const解释

    In my last column, I discussed one of the reasons why the rules by which a compiler can place data i ...