通常在涉及到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. Linux权限简析

  2. 树莓派安装omv

    1.Win32DiskImager写入光盘镜像 2.进入omv页面 设置 ip 端口号 ,设置时间,设置ssh打开,设置会话超时时间 ××××设置 dns  很重要!! #这里用的是阿里云的DNS服务 ...

  3. TLS/SSL 协议 - ServerKeyExchange、ServerHelloDone

    ServerKeyExchange ServerKeyExchange消息的目的是携带密钥交换的额外数据.消息内容对于不同的协商算法套件都会存在差异.在某些场景中,服务器不需要发送任何内容,这意味着在 ...

  4. jsp2自定义标签开篇

    在JSP2中开发标签库需要以下几个步骤: 1.开发自定义标签处理类: 2.建立一个*.tld文件,每个*.tld文件对应一个标签库,每个标签库可包含多个标签: 3.在JSP文件中使用自定义标签. 第一 ...

  5. Apache配置 PHP 支持

    1,在服务区安装PHP 解压 php 到纯英文路径目 2,添加 PHP处理模块 LoadModule php7_module C:/ProgramData/php/php7apache2_4.dl 3 ...

  6. MySQL 8.0及以上版本设置密码

    ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';

  7. C# WinfForm 控件之dev报表 XtraReport (二) 固定数据绑定

    已经子解了XtraReport的初步用法 现在再进一步了解 数据绑定 我们还是先不整高深的 先来个写死的 让我们的数据库数据可以通过报表呈现先 1.准备 还在上节基础上 只不过我把form1 中的Do ...

  8. (数据科学学习手札57)用ggplotly()美化ggplot2图像

    一.简介 经常利用Python进行数据可视化的朋友一定用过或听说过plotly这样的神器,我在(数据科学学习手札43)Plotly基础内容介绍中也曾做过非常详细的介绍,其渲染出的图像以浏览器为载体,非 ...

  9. mongo之$max

    原集合: { _id: 1, highScore: 800, lowScore: 200 } 应用: #意思是:更新_id 等于1 的记录,条件是highScore 950>原纪录的highSc ...

  10. opencv2.4.9+vs2012安装配置

    需要下载并安装vs2012  http://pan.baidu.com/s/1qXP76CO     第一次启动会提示要求输入激活序列号,请输入:YKCW6-BPFPF-BT8C9-7DCTH-QXG ...