zoukankan      html  css  js  c++  java
  • StringBuilder && StringBuffer原理浅析

    本文主要以简单的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("
    ");
            stringBuilder.append("Country:").append(strCountry).append("
    ");
    
            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("
    ");
            stringBuffer.append("Country:").append(strCountry).append("
    ");
    
            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。

  • 相关阅读:
    Codevs 2296 仪仗队 2008年省队选拔赛山东
    Codevs 1535 封锁阳光大学
    Codevs 1069 关押罪犯 2010年NOIP全国联赛提高组
    Codevs 1218 疫情控制 2012年NOIP全国联赛提高组
    Codevs 1684 垃圾陷阱
    洛谷 P1108 低价购买
    Vijos P1325桐桐的糖果计划
    Codevs 3289 花匠 2013年NOIP全国联赛提高组
    Codevs 2611 观光旅游(floyed最小环)
    C语言基础之彩色版C语言(内含linux)
  • 原文地址:https://www.cnblogs.com/xinxinBlog/p/10176838.html
Copyright © 2011-2022 走看看