码迷,mamicode.com
首页 > 其他好文 > 详细

StringBuilder && StringBuffer原理浅析

时间:2018-12-25 22:55:09      阅读:221      评论:0      收藏:0      [点我收藏+]

标签:原理   main   count   ringbuf   aci   sci   final   容量   throw   

本文主要以简单的String/StringBuilder/StringBuffer操作来看这三个类的实现原理。
什么简单操作呢?那就是StringBuilder与StringBuffer的append() && toString()两个方法。
示例代码如下:

public class TestStringBuffer_Builder {

    public static void main(String[] args) {
        TestStringBuffer_Builder testStringBuffer_builder = new TestStringBuffer_Builder();
        testStringBuffer_builder.testStringBuilder();
        testStringBuffer_builder.testStringBuffer();
    }

    public void testStringBuilder()
    {
        String strName = new String("JackMa");
        String strCountry = new String("China");

        StringBuilder stringBuilder = new StringBuilder(64);
        stringBuilder.append("Name:").append(strName).append("\n");
        stringBuilder.append("Country:").append(strCountry).append("\n");

        System.out.print(stringBuilder.toString());
    }

    private void testStringBuffer()
    {
        String strName = new String("JackMa");
        String strCountry = new String("China");

        StringBuffer stringBuffer = new StringBuffer(64);
        stringBuffer.append("Name:").append(strName).append("\n");
        stringBuffer.append("Country:").append(strCountry).append("\n");

        System.out.print(stringBuffer.toString());
    }
}

 

以上的demo中,涉及到了String的构造,StringBuilder & StringBuffer的构造、append与toString。我们分别研究这几个方法,来了解其内部的实现原理。

一、String
代码中首先构造了String。
先简单看看String内部发生了什么:

public final class String
{
	private final char value[];
	private int hash;

	public String() {
		this.value = "".value;
	}

	public String(String original) {
		this.value = original.value;
		this.hash = original.hash;
	}

	public String(char value[]) {
		this.value = Arrays.copyOf(value, value.length);
	}
	
	public String concat(String str) {
        int otherLen = str.length();
        if (otherLen == 0) {
            return this;
        }
        int len = value.length;
        char buf[] = Arrays.copyOf(value, len + otherLen);
        str.getChars(buf, len);
        return new String(buf, true);
    }
}

可以看的出来,String中的数据都是保存在数组char value[]中。
对于String的concat(拼接)过程可以看出,最后生成了一个新的String对象作为拼接的结果。

  

二、StringBuilder
先看看StringBuilder中的方法:

public class StringBuilder
		extends AbstractStringBuilder
{
	public StringBuilder(int capacity) {
		super(capacity);
	}
	
	public StringBuilder append(String str) {
        super.append(str);
        return this;
    }
}
父类:
public abstract class AbstractStringBuilder
{
	char[] value;
	
	AbstractStringBuilder(int capacity) {
		value = new char[capacity];
	}
	
	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;
    }
	
	private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0)
            expandCapacity(minimumCapacity);
    }
	
	void expandCapacity(int minimumCapacity) {
        int newCapacity = value.length * 2 + 2;
        if (newCapacity - minimumCapacity < 0)
            newCapacity = minimumCapacity;
        if (newCapacity < 0) {
            if (minimumCapacity < 0) // overflow
                throw new OutOfMemoryError();
            newCapacity = Integer.MAX_VALUE;
        }
        value = Arrays.copyOf(value, newCapacity);
    }
	
	public String toString() {
        // Create a copy, don‘t share the array
        return new String(value, 0, count);
    }
}

  

StringBuilder中也是用数组进行数据保存。相比于String的concat操作,StringBuilder在拼接字符串的过程始终是一个对象在操作,变化的是StringBuilder内部的数组若容量不够,则进行扩充
扩容算法中,在拼接字符串不长的情况下,容量通常扩为2倍。若2倍不足,则扩为需要的大小。
在toString方法中,使用StringBuilder内部的value数组构造一个新的的String对象,并返回。

 

三、StringBuffer

public final class StringBuffer 
		extends AbstractStringBuilder
{
	private transient char[] toStringCache;
	
	public synchronized StringBuffer append(String str) 
	{
		toStringCache = null;
		super.append(str);
		return this;
	}
	
	public synchronized String toString() {
        if (toStringCache == null) {
            toStringCache = Arrays.copyOfRange(value, 0, count);
        }
        return new String(toStringCache, true);
    }
}

  

StringBuffer中,也是用数组进行字符串数据保存。不同于StringBuilder,StringBuffer中的操作字符串方法是同步的,因此属于线程安全
同时用了transient char[] toStringCache来缓存数据。在调用toString时,将字符串内容保存进toStringCache, 且在修改StringBuffer时(例如append、insert、delete等字符操作),清空该缓存。
若字符串无修改,在第二次调用toString时直接将缓存内容返回,从而提升字符转换效率

这里面涉及到一个点:用于缓存字符内容的数组toStringCache是用transient修饰,直接访问内存,从而实现线程间的可见性。具体内容可进一步了解关键字transient。

 

StringBuilder && StringBuffer原理浅析

标签:原理   main   count   ringbuf   aci   sci   final   容量   throw   

原文地址:https://www.cnblogs.com/xinxinBlog/p/10176838.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!