欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

荐 21. Java基础之StringBuffer和StringBuilder

程序员文章站 2022-05-18 17:47:46
操作少量的数据: 适用String单线程操作字符串缓冲区下操作大量数据: 适用StringBuilder多线程操作字符串缓冲区下操作大量数据: 适用StringBuffer...

Java基础之StringBuffer和StringBuilder

1. 前言-浅谈String:

  1. String 类中使用 final 关键字修饰字符数组来保存字符串, private final char value[] ,所以String 对象是不可变的。
  2. String 中的对象是不可变的,也就可以理解为常量,线程安全。
  3. 每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象。
  4. String类传送门…

2. 可变的StringBuffer和StringBuilder

  1. StringBuilder 与 StringBuffer 都继承自 AbstractStringBuilder 类,在AbstractStringBuilder 中也是使用字符数组保存字符串 char[] value 但是没有用 final 关键字修饰,所以这两种对象都是可变的。
  2. StringBuilder 与 StringBuffer 的构造方法都是调用父类构造方法也就是 AbstractStringBuilder 实现的,大家可以看下面的源码分析。

3. 线程安全性

AbstractStringBuilder 是 StringBuilder 与StringBuffer 的公共父类,定义了一些字符串的基本操作,如 append、insert、indexOf 等公共方法。

  • StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。
  • StringBuilder 并没有对方法进行加同步锁,所以是线程不安全的。

4. 性能

StringBuffer 每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。

相同情况下使用StringBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。

5. AbstractStringBuilder部分源码

可变的字符序列–基于JDK1.8

/**
*可变的字符序列
*/
abstract class AbstractStringBuilder implements Appendable, CharSequence {
    
  char[] value;//该值用于字符存储。
  int count;//计数是使用的字符数。
    
  // 此no-arg构造函数对于子类的序列化是必需的。
  AbstractStringBuilder() {
 }
  // 创建指定容量的AbstractStringBuilder。
  AbstractStringBuilder(int capacity) {
    value = new char[capacity];
 }
 // 一系列方法...
}
5.1 StringBuffer部分源码

注意StringBuffer中方法中的synchronized锁

 public final class StringBuffer extends AbstractStringBuilder 
    implements java.io.Serializable, CharSequence{

    /**
     *将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会被序列化。
     *toString返回的最后一个值的缓存。每当修改StringBuffer时清除。
     */
    private transient char[] toStringCache;
     
    static final long serialVersionUID = 3388685877147921107L;

    /**
     * Constructs a string buffer with no characters in it and an
     * initial capacity of 16 characters.
     */
    public StringBuffer() {
        super(16);
    }

    public StringBuffer(int capacity) {
        super(capacity);
    }

    public StringBuffer(String str) {
        super(str.length() + 16);
        append(str);
    }

    public StringBuffer(CharSequence seq) {
        this(seq.length() + 16);
        append(seq);
    }

    @Override
    public synchronized int length() {
        return count;
    }

    @Override
    public synchronized int capacity() {
        return value.length;
    }
    
    /**
    * 有一系列的方法的重载...
    */
    @Override
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }
    /**
    * 有一系列的方法的重载...
    */
    @Override
    public synchronized StringBuffer insert(
        int index, char[] str, int offset,int len
    ){
        toStringCache = null;
        super.insert(index, str, offset, len);
        return this;
    }
 }

length()和capacity()两个方法以及默认构造器的测试:

    public static void main(String[] args) {
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("dd");
        stringBuffer.append("ai");
        stringBuffer.append("mm");
        /**
         * stringBuffer.length() = 6
         * stringBuffer.capacity() = 16
         */
        System.out.println("stringBuffer.length() = " + stringBuffer.length());
        System.out.println("stringBuffer.capacity() = " + stringBuffer.capacity());
        
    }
		/**
		* 当添加的字符超过16之后,该buffer容量为34
		* stringBuffer.length() = 17
		* stringBuffer.capacity() = 34
		*/

一系列的重载方法:

荐
                                                        21. Java基础之StringBuffer和StringBuilder

5.2 StringBuilder部分源码
public final class StringBuilder extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
{

    /** use serialVersionUID for interoperability */
    static final long serialVersionUID = 4383685877147921099L;
    
    // 三个构造器和StringBuffer中的是一样的
    public StringBuilder() {
        super(16);
    }
    
    public StringBuilder(int capacity) {
        super(capacity);
    }

    public StringBuilder(String str) {
        super(str.length() + 16);
        append(str);
    }

    // 也是一系列的方法重载。
    @Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }
    
    public StringBuilder append(StringBuffer sb) {
        super.append(sb);
        return this;
    }
    
    // 也是一系列的方法重载。
    @Override
    public StringBuilder insert(
        int index, char[] str, int offset,int len
    ){
        super.insert(index, str, offset, len);
        return this;
    }
    
    // ...
}

6. 小结:

  1. 操作少量的数据: 适用String
  2. 单线程操作字符串缓冲区下操作大量数据: 适用StringBuilder
  3. 多线程操作字符串缓冲区下操作大量数据: 适用StringBuffer

本文地址:https://blog.csdn.net/weixin_45267102/article/details/107348280