通常在涉及到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. Ubuntu12.04下安装sourcenavigator-NG4.5阅读源代码

    大家知道Windows下有一个很好的查看源代码的软件sourceinsight,使用sourceinsight查看Linux内核代码.嵌入式软件开发中的C语言项目源代码.驱动程序代码很是方便.在Lin ...

  2. UI自动化ADB出现devices offline的解决方法

    终端运行如下命令即可解决: adb kill-server adb start-server adb remount

  3. vue 在微信中设置动态标题

    1.安装插件 cnpm install vue-wechat-title --save 2.在main.js中引入 import VueWechatTitle from 'vue-wechat-tit ...

  4. akka-stream之异常处理

    背景介绍 在项目中使用了akk-stream的source.queue功能,如下: Pair<SourceQueueWithComplete<Integer>, Source< ...

  5. ArcGis EsriAddin加载项的安装路径与程序启动路径

      安装路径: 在C:\Users\用户名\Documents\ArcGIS\AddIns\Desktop版本号\{…………一组GUID…………}这样的路径下.  例:C:\Users\Adminis ...

  6. JVM调优参数设置?

    -Xms20M 表示设置堆容量的最小值为20M,必须以M为单位 -Xmx20M 表示设置堆容量的最大值为20M,必须以M为单位.将-Xmx和-Xms设置为一样可以避免堆自动扩展.大的项目-Xmx和-X ...

  7. css3 一个六边形 和 放大旋转动画DEMO演示

    <!DOCTYPE html> <html> <head> <meta charset="gb2312"> <title> ...

  8. Flask理论基础(一)视图函数和URL反转函数(url_for)

    一.视图函数 1.1 基本用法试图函数是 app.route 或者 bp.route(蓝图)装饰器装饰的函数.该函数实现了对URL路径的转换,也就是路由功能,例如下面代码定义了默认url ‘/’ 和‘ ...

  9. zmq的send

    int zmq_send (void *socket, zmq_msg_t *msg, int flags);      2.2.1 nt zmq_send (void *socket, void * ...

  10. Mysql 编译报错 g++: internal compiler error: Killed (program cc1plus) 解决办法

    g++: internal compiler error: Killed (program cc1plus) 解决办法 g++: internal compiler error: Killed (pr ...