JDK源码阅读03---------AbstractStringBuilder、StringBuffer、StringBuilder

1.AbstractStringBuilder、StringBuffer、StringBuilder类简介

字符串广泛应用 在Java 编程中,在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串。

需要注意的是,String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,这样不仅效率低下,而且大量浪费有限的内存空间。

String是Java语言非常基础和重要的类,提供了构造和管理字符串的各种基本逻辑。它是典型的Immutable类,被声明成为final class,所有属性也都是final 的。也由于它的不可变性,类似拼接、裁剪字符串等动作,都会产生新的String对象。由于字符串操作的普遍性,所以相关操作的效率往往对应用性能有明显影响

StringBuffer是为解决上面提到拼接产生太多中间对象的问题而提供的一个类,我们可以用append或者add方法,把字符串添加到已有序列的末尾或者指定位置。StringBuffer 本质是一个线程安全的可修改字符序列,它保证了线程安全,也随之带来了额外的性能开销,所以除非有线程安全的需要,不然还是推荐使用它的后继者,也就是StringBuilder.

StringBuilder是Java 1.5中新增的,在能力上和StringBuffer没有本质区别,但是它去掉了线程安全的部分,有效减小了开销,是绝大部分情况下进行字符串拼接的首选。

StringBufferStringBuilder 底层都是利用可修改的(char,JDK 9 以后是 byte)数组,二者都继承了AbstractStringBuilder,里面包含了基本操作,区别仅在于最终的方法是否加了 synchronized

2.源码阅读

StringBufferStringBuilder都是继承的AbstractStringBuilder,二者中的主要方法与变量与AbstractStringBuilder都类似,StringBufferStringBuilder 的区别主要在于最终的方法是否加了synchronized关键字,这里源码主要以AbstractStringBuilder为主,有区别的地方再另行标注。

  • 2.1 类定义
/**
	 *AbstractStringBuilder
     	*实现了两个接口,其中CharSequence这个字符序列的接口已经很熟悉了:
	   该接口规定了需要实现该字符序列的长度:length();
		可以取得下标为index的的字符:charAt(int index);
		可以得到该字符序列的一个子字符序列: subSequence(int start, int end);
		规定了该字符序列的String版本(重写了父类Object的toString()):toString();
		
	   Appendable接口顾名思义,定义添加的’规则’:
		append(CharSequence csq) throws IOException:如何添加一个字符序列
		append(CharSequence csq, int start, int end) throws IOException:如何添加一个字符序列的一部分
		append(char c) throws IOException:如何添加一个字符
     *
     */
	abstract class AbstractStringBuilder implements Appendable, CharSequence {}
	
	public final class StringBuffer    extends AbstractStringBuilder implements java.io.Serializable, CharSequence{}

	public final class StringBuilder    extends AbstractStringBuilder    implements java.io.Serializable, CharSequence{}
  • 2.2变量
    AbstractStringBuilder
/**
     * 用于存储字符序列的缓冲数组
     */
    char[] value;

    /**
     * 用于存储实际存储的字符数量
     */
    int count;
    
	 /**
     * 缓冲数组最大长度(2^31-1)-8 约为21亿
     */
	private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

StringBuffer中特有的toStringCache,用来缓存StringBuffer最近一次toString的值,当StringBuffer出现任何其他操作或修改后,清空缓存值。

 /**
     * A cache of the last value returned by toString. Cleared
     * whenever the StringBuffer is modified.
     */
    private transient char[] toStringCache;
  • 2.3构造方法
    AbstractStringBuilder
    AbstractStringBuilder() {
    }
    AbstractStringBuilder(int capacity) {
        value = new char[capacity];
    }

StringBuilder与StringBuffer的构造器基本相同,默认初始化数组长度为,构建时初始字符串长度加 16

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);
    }
  • 2.4常用方法
    /**
     * 获取字符串长度
     */
    @Override
    public int length() {
        return count;
    }
    
    /**
     * 获取缓冲区的容量
     */
    public int capacity() {
        return value.length;
    }

扩容相关实现:
扩容时,当现有容量值*2+2<所需最小容量时,取所需最小容量
现有容量值*2+2>=所需最小容量时,取 现有容量*2+2

 /**
     * 缓冲数组容量校验
     * 放入缓冲数组所需要的的最小容量 
     */
    public void ensureCapacity(int minimumCapacity) {
        if (minimumCapacity > 0)
            ensureCapacityInternal(minimumCapacity);
    }

    /**
     * 当所需要的最小容量>当前数组的容量时,取最小容量,创建新数组,复制
     */
    private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }

    /**
     * 缓冲数组最大长度(2^31-1)-8 约为21亿
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    /**
     *  创建一个新容量的数组:
     *  当所需新容量>现有容量*2+2 时,取所需新容量大小
     *  当新建新容量大小<0时,取最小容量
     *  
     */
    private int newCapacity(int minCapacity) {
        // overflow-conscious code
        int newCapacity = (value.length << 1) + 2;
        if (newCapacity - minCapacity < 0) {
            newCapacity = minCapacity;
        }
        return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
            ? hugeCapacity(minCapacity)
            : newCapacity;
    }
	/**
     *  当新建新容量>Integer.MAX_VALUE时,抛OutOfMemoryError();
     *  当 MAX_ARRAY_SIZE<minCapacity <Integer.MAX_VALUE时,取minCapacity 
     */
    private int hugeCapacity(int minCapacity) {
        if (Integer.MAX_VALUE - minCapacity < 0) { // overflow
            throw new OutOfMemoryError();
        }
        return (minCapacity > MAX_ARRAY_SIZE)
            ? minCapacity : MAX_ARRAY_SIZE;
    }

关于“空格”相关的方法:

	/**
     *  将缓存数组中的非空字符序列拷贝到新的数组中
     */
		public void trimToSize() {
	        if (count < value.length) {
	            value = Arrays.copyOf(value, count);
	        }
	    }

    /**
     * 该函数没有返回值。 
	   若参数 newLength 大于或等于原长度,原来字符串里的字符位置不变,新多出来的位置					    	用 空字符(‘\0’)填充; 
	   若参数 newLength 小于原长度,就相当于在原字符串上截取 newLength 长度的字符串。 
newLength >= 0
     */
    public void setLength(int newLength) {
        if (newLength < 0)
            throw new StringIndexOutOfBoundsException(newLength);
        ensureCapacityInternal(newLength);
        if (count < newLength) {
            Arrays.fill(value, count, newLength, '\0');
        }
        count = newLength;
    }

AbstractStringBuilder中的append()方法,主要实现思路就是先确定容量,再通过getChars()方法或者遍历字符来将所需要的字符串信息追加至缓冲数组中.

 public AbstractStringBuilder append(Object obj) {
        return append(String.valueOf(obj));
    }
    
public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }

    // Documentation in subclasses because of synchro difference
    public AbstractStringBuilder append(StringBuffer sb) {
        if (sb == null)
            return appendNull();
        int len = sb.length();
        ensureCapacityInternal(count + len);
        sb.getChars(0, len, value, count);
        count += len;
        return this;
    }
    /**
     * @since 1.8
     */
    AbstractStringBuilder append(AbstractStringBuilder asb) {
        if (asb == null)
            return appendNull();
        int len = asb.length();
        ensureCapacityInternal(count + len);
        asb.getChars(0, len, value, count);
        count += len;
        return this;
    }
    ....
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值