MENU

Java-52 常用类之StringBuffer和StringBuilder

November 7, 2023 • Read: 67 • Java阅读设置

StringBuffer&StringBuilder

1 StringBuffer和StringBuilder是什么

String类一样,StringBufferStringBuilder也是表示字符串的类。

String vs StringBufferStringBuilder
1) 相同点:

  • 三者都是表示字符串的类;
  • 三者在底层都是用char型数组来表示字符串的值。具体地,String类是有一个私有char型数组属性value来表示字符串的值;StringBufferStringBuilder是都继承于一个抽象类AbstractStringBuilder,继承了该抽象类中的char型数组属性value来表示字符串的值。
    2023-11-07T07:39:26.png

2) 不同点:

  • String是表示不变的字符串;而StringBufferStringBuilder是表示可变的字符串,从源码上看对应的表示字符串值的value属性也是前者是final的,后者并不是。

StringStringBufferStringBuilder底层都是用char型数组来表示字符串的值,但StringBufferStringBuilder是可变的字符串的源码分析:

  • String中表示字符串值的属性valuefinal的,因此只要String对象对应的字符串改变了,只能用以新字符串为value的对应的新的String对象来替换。因此,String代表的是不可变字符串,一旦改变就是改变了对象。
  • StringBufferStringBuilder中表示字符串值的属性value不是final的,因此即使其对应对象的字符串改变了,也只是对应对象其中的value属性改变了,对应的对象并没有改变。
    StringBufferStringBuilder中表示字符串值的属性value本身就是char型数组,一个引用类型数据,其引用的数组(即value对应的地址值)也不是随着对应字符串改变就一定改变。因为在构造StringBufferStringBuilder对象时,其对应的char型数组属性value是具有容量capacity的,也就是说,StringBufferStringBuilder对象对应的字符串的改变或者表示都是基于capacity长度的char型数组,只有当对应字符串因为改变超出了capacity长度,才会导致对应value属性引用的地址值改变。
    具体源码分析如下,以StringBuffer为例,在以下方面StringBuilderStringBuffer没有区别:

    • StringBuffer有四个构造器:空参构造器、指定capacity的构造器、指定字符串的构造器和指定CharSequence(也理解为指定字符串)的构造器。
      对于空参构造器public StringBuffer(),它是构造一个表示空字符串的对应字符串对象,但是底层是具有16个字符长度的。
      2023-11-07T08:26:23.png
      2023-11-07T08:26:37.png
      2023-11-07T08:26:53.png

    对于指定capacity的构造器public StringBuffer(int capacity),就是构造一个表示空字符串的对应字符串对象,但是底层对应字符数组长度为指定长度。
    2023-11-07T08:27:57.png
    2023-11-07T08:28:25.png
    2023-11-07T08:28:37.png

    对于指定字符串的构造器public StringBuffer(String str),是构造一个表示对应字符串的对应字符串对象,但是底层对应字符数组长度为16+指定字符串的长度。由于源码是用了str.length来创建char型数组,因此如果strnull,会产生空指针异常。
    2023-11-07T08:30:02.png
    2023-11-07T08:30:16.png

    • StringBufferappend方法就是在底层char型数组中已有的字符后面加上新的字符或字符串,简单地说,就是利用底层char型数组还没被利用的容量。根据源码可知,当append的新字符或字符串的长度与原有字符串长度之和超过底层char型数组的长度时,就会利用数组复制方法进行扩容,即开辟一个新的更大的char型数组并将新字符或字符串的长度与原有字符串一起复制过来,作为value属性的新的地址值。
      具体扩容的长度默认为原capacity×2+2。
      2023-11-07T08:33:14.png
      2023-11-07T08:33:38.png
      2023-11-07T08:34:01.png
      2023-11-07T08:41:54.png

StringBuffer vs StringBuilder
StringStringBuffer都是JDK1.0就存在的,StringBuilder是JDK5新增的。
StringBufferStringBuilder是相同的,区别在于,StringBuffer是安全的,其所有方法都具有同步机制,而StringBuilder是专为单线程设计的,不安全的,可以理解为StringBuffer的无同步机制版本。因此,StringBuilder相比于`StringBuffer效率更高。
2023-11-07T08:47:35.png

总的来说,StringBufferStringBuilder都是表示可变字符串的,它们底层用了具有一定长度的char型数组并配合count属性(表示有效字符的属性)来表示字符串,方法都是继承自抽象类AbstractStringBuilderStringBuffer具有同步机制,而StringBuilder没有。

由于StringBufferStringBuilder就是用来表示可变字符串的,并且字符串改变引起的扩容会影响效率,因此在使用时,推荐用能够指定capacity的构造器来构造对应的对象来使用。

对于StringStringBufferStringBuilder的效率是以此递增的,String效率最低,因为每次改变都要重新创建新的对应对象。

2 StringBuffer和StringBuilder的方法

StringBuffer为例,StringBuilder与其一样,区别仅在于有无同步机制。
StringBuffer对象表示的字符串本来就是可变的,这些方法中,有些方法之所以返回类型也为StringBuffer,实际上其源码返回的就是this

  • public StringBuffer append(type argument):该方法就是在对应StringBuffer对象表示的字符串的末尾加上指定的参数对应的字符串。该方法的参数适用于int、long、float、double、char、boolean、char[]、String、StringBuffer、Object,原理实际上就是将对应参数对应的toString的结果加到对应StringBuffer对象表示的字符串的末尾。
    参数为char[]时,也可以同时指定将数组中哪个位置开始的、长度为多少的字符加到对应StringBuffer对象表示的字符串的末尾。
    注意,如果参数为null时,append方法将会把字符串"null"四个字符加进对应StringBuffer对象表示的字符串的末尾。
    2023-11-07T10:25:15.png
    2023-11-07T10:25:26.png
    2023-11-07T10:26:03.png
    2023-11-07T10:28:50.png
  • public StringBuffer insert(int offset, type argument):该方法就是在对应StringBuffer对象表示的字符串中的指定索引位置插入指定的参数对应的字符串。该方法的适用参数与append()方法相同,原理也类似。所有重载方法中的第一个参数都是指定对应StringBuffer对象表示的字符串中的插入索引位置,第二个参数一般为要插入的对象。
    参数为char[]时,也可以同时指定将数组中哪个位置开始的、长度为多少的字符插入到对应StringBuffer对象表示的字符串的指定索引位置。
    注意,如果参数为null时,insert方法将会把字符串"null"四个字符加进对应StringBuffer对象表示的字符串的末尾。
    2023-11-07T10:41:45.png
    2023-11-07T10:41:13.png
    2023-11-07T10:41:29.png
    2023-11-07T10:42:48.png
  • public StringBuffer appendCodePoint(int codePoint):该方法将指定的Unicode码对应的字符加到对应StringBuffer对象表示的字符串的末尾。
    2023-11-07T10:43:46.png
  • public int capacity():该方法返回对应StringBuffer对象的容量。
    2023-11-07T10:45:35.png
  • public int length():该方法返回对应StringBuffer对象表示的字符串的长度。
    2023-11-07T10:46:13.png
    2023-11-07T10:46:24.png
  • public char charAt(int index):该方法返回对应StringBuffer对象表示的字符串中指定索引位置的字符。
    2023-11-07T10:47:07.png
  • public StringBuffer delete(int start, int end):该方法删除对应StringBuffer对象表示的字符串中指定开始到结尾位置的字符,左闭右开。
    2023-11-07T10:48:42.png
  • public StringBuffer deleteCharAt(int index):该方法删除对应StringBuffer对象表示的字符串中指定索引位置的字符。
    2023-11-07T10:49:19.png
  • public void ensureCapacity(int minimumCapacity):该方法确保对应StringBuffer对象的容量不小于指定的容量,如果小于,则会扩容,扩容后的容量大小要么为指定的容量,要么为当前StringBuffer对象的容量的两倍加2。
    2023-11-07T10:52:24.png
    2023-11-07T10:52:32.png
  • public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin):该方法将对应StringBuffer对象表示的字符串中指定开始到结束位置的字符复制到指定的char型数组中,并指定指定的char型数组的复制开始位置。该方法不会改变指定char型数组的长度,等同于将指定char型数组的指定位置开始的字符替换为StringBuffer对象表示的字符串中指定开始到结束位置的字符。
    2023-11-07T10:55:50.png
  • public int indexOf(String str):该方法返回对应StringBuffer对象表示的字符串中指定的字符串第一次出现的索引位置,如果没有出现,则返回-1。
    2023-11-07T10:58:39.png
    2023-11-07T10:57:08.png
    2023-11-07T10:58:10.png
    2023-11-07T10:58:49.png
  • public StringBuffer replace(int start, int end, String str):该方法将用指定的字符串替换对应StringBuffer对象表示的字符串中指定开始到结束位置的字符,左闭右开。该方法可以改变对应StringBuffer对象表示的字符串的长度。该方法本质上是先删除掉指定字符串中指定开始到结束位置的字符,再插入指定的字符串。
    2023-11-07T11:03:20.png
    2023-11-07T11:03:29.png
  • public StringBuffer reverse():该方法将对应StringBuffer对象表示的字符串进行反转。
    2023-11-07T11:05:32.png
    2023-11-07T11:05:40.png
  • public void setCharAt(int index, char ch):该方法将对应StringBuffer对象表示的字符串中的指定索引位置的字符修改为指定字符。
    2023-11-07T11:06:28.png
  • public void setLength(int newLength):该方法设置对应StringBuffer对象表示的字符串的长度,如果新长度大于原长度,则多出的长度用字符代表null的字符填充,如果新长度小于原长度,则会截断字符串至新长度。
    2023-11-07T11:11:31.png
    2023-11-07T11:11:40.png
  • public String substring(int start):该方法返回对应StringBuffer对象表示的字符串从指定索引位置开始到最后的字符对应的字符串。
    2023-11-07T11:12:53.png
  • public String substring(int start, int end):上个方法的指定结束位置的版本。
  • public String toString():该方法返回对应StringBuffer对象表示的字符串的String版本。
    2023-11-07T11:14:25.png
  • public void trimToSize():该方法会根据对应StringBuffer对象表示的字符串的长度以及其对应的容量,来调整容量至当前字符串长度的容量。
    2023-11-07T11:17:06.png
    2023-11-07T11:17:26.png

注意示例:
2023-11-08T12:27:40.png

Last Modified: November 8, 2023