StringBuilder、StringBuffer分析比较
程序员文章站
2023-09-07 21:05:49
StringBuilder、StringBuffer源码分析 StringBuilder源码分析 类结构 StringBuilder使用final关键字修饰,和String一样不可以被继承 StringBuilder继承AbstractStringBuilder并实现了Serializable和Ch ......
stringbuilder、stringbuffer源码分析
stringbuilder源码分析
类结构
public final class stringbuilder extends abstractstringbuilder implements java.io.serializable, charsequence
stringbuilder使用final关键字修饰,和string一样不可以被继承
stringbuilder继承abstractstringbuilder并实现了serializable和charsequence,可以被序列化
方法
stringbuilder 的方法多是直接调用父类abstractstringbuilder的方法,这里找几个典型的方法看一下
stringbuilder append(object obj)方法重写父类的方法,追加object类型的元素
@override public stringbuilder append(object obj) { return append(string.valueof(obj));//string.valueof(obj)获取对象转换成的字符串 } public static string valueof(object obj) { return (obj == null) ? "null" : obj.tostring(); } @override public stringbuilder append(string str) { super.append(str); return this; } public abstractstringbuilder append(string str) { if (str == null) return appendnull();//如果为null追加字符串“null” int len = str.length(); ensurecapacityinternal(count + len); //拷贝字符串到数组 str.getchars(0, len, value, count); count += len; return this; }
stringbuilder delete(int start, int end)删除指定起点下标到指定结束下标的字符
@override public stringbuilder delete(int start, int end) { super.delete(start, end); return this; } public abstractstringbuilder delete(int start, int end) { if (start < 0) throw new stringindexoutofboundsexception(start); if (end > count)//如果结束下标>当前保存char的最大下标,直接赋值为最大下标 end = count; if (start > end) throw new stringindexoutofboundsexception(); int len = end - start; if (len > 0) { //把删除尾下标后的元素拷贝到删除起始下标后 system.arraycopy(value, start+len, value, start, count-end); count -= len; } return this; }
stringbuilder replace(int start, int end, string str)使用字符串替换指定范围内的字符
@override public stringbuilder replace(int start, int end, string str) { super.replace(start, end, str); return this; } public abstractstringbuilder replace(int start, int end, string str) { if (start < 0) throw new stringindexoutofboundsexception(start); if (start > count) throw new stringindexoutofboundsexception("start > length()"); if (start > end) throw new stringindexoutofboundsexception("start > end"); if (end > count) end = count; int len = str.length(); //计算需要的容量 int newcount = count + len - (end - start); //扩容 ensurecapacityinternal(newcount); //删除指定范围的字符 system.arraycopy(value, end, value, start + len, count - end); //在删除的起始位置插入字符串 str.getchars(value, start); count = newcount; return this; }
stringbuilder insert(int offset, object obj)在指定位置插入对象
@override public stringbuilder insert(int offset, object obj) { super.insert(offset, obj); return this; } public abstractstringbuilder insert(int offset, object obj) { return insert(offset, string.valueof(obj));//string.valueof(obj)获取对象转换的字符串 } public static string valueof(object obj) { return (obj == null) ? "null" : obj.tostring(); } @override public stringbuilder insert(int offset, string str) { super.insert(offset, str); return this; } public abstractstringbuilder insert(int offset, string str) { if ((offset < 0) || (offset > length())) throw new stringindexoutofboundsexception(offset); if (str == null) str = "null"; int len = str.length(); //扩容 ensurecapacityinternal(count + len); //把要插入位置后一定数量的字符(插入字符串长度)串移动后移一定距离(插入字符串长度) system.arraycopy(value, offset, value, offset + len, count - offset); //插入要插入的字符串 str.getchars(value, offset); count += len; return this; }
可以看到,stringbuilder的append、insert、replace、delete都是对父类的char数组进行的一些操作,并没有产生新的对象
string tostring() 最精髓的一个方法
@override public string tostring() { //把进过一些列修改后的最终char数组生成string return new string(value, 0, count); }
这里我们看到在tostring的时候,把char数组生成了string,这也是为什么stringbuilder比string效率高的原因,string类没做一点修改都会生成新的对象,那么在频繁拼串和截取字符串时,效率当然不如stringbuilder
stringbuffer源码分析
类结构
public final class stringbuffer extends abstractstringbuilder implements java.io.serializable, charsequence
stringbuffer的类结构和stringbuilder的一样
方法
stringbuffer和stringbuilder一样,很多方法都是调用父类abstractstringbuilder的方法,我们看几个最主要的方法
stringbuffer append(object obj)向stringbuffer中追加对象,和stringbuilder的追加对象一样的代码
@override public synchronized stringbuffer append(object obj) { tostringcache = null; super.append(string.valueof(obj)); return this; } 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; } public void getchars(int srcbegin, int srcend, char dst[], int dstbegin) { if (srcbegin < 0) { throw new stringindexoutofboundsexception(srcbegin); } if (srcend > value.length) { throw new stringindexoutofboundsexception(srcend); } if (srcbegin > srcend) { throw new stringindexoutofboundsexception(srcend - srcbegin); } system.arraycopy(value, srcbegin, dst, dstbegin, srcend - srcbegin); }
stringbuffer delete(int start, int end)删除指定范围内的字符,和stringbuilder中delete方法代码一样
@override public synchronized stringbuffer delete(int start, int end) { tostringcache = null; super.delete(start, end); return this; } public abstractstringbuilder delete(int start, int end) { if (start < 0) throw new stringindexoutofboundsexception(start); if (end > count) end = count; if (start > end) throw new stringindexoutofboundsexception(); int len = end - start; if (len > 0) { system.arraycopy(value, start+len, value, start, count-end); count -= len; } return this; }
stringbuffer replace(int start, int end, string str)方法使用字符串替换指定范围内的字符,和stringbuilder的replace方法代码一样
@override public synchronized stringbuffer replace(int start, int end, string str) { tostringcache = null; super.replace(start, end, str); return this; } public abstractstringbuilder replace(int start, int end, string str) { if (start < 0) throw new stringindexoutofboundsexception(start); if (start > count) throw new stringindexoutofboundsexception("start > length()"); if (start > end) throw new stringindexoutofboundsexception("start > end"); if (end > count) end = count; int len = str.length(); int newcount = count + len - (end - start); ensurecapacityinternal(newcount); system.arraycopy(value, end, value, start + len, count - end); str.getchars(value, start); count = newcount; return this; }
stringbuffer insert(int offset, object obj)在指定位置插入字符串,也是和stringbuilder的insert方法代码一样
@override public synchronized stringbuffer insert(int offset, object obj) { tostringcache = null; super.insert(offset, string.valueof(obj)); return this; } public abstractstringbuilder insert(int offset, string str) { if ((offset < 0) || (offset > length())) throw new stringindexoutofboundsexception(offset); if (str == null) str = "null"; int len = str.length(); ensurecapacityinternal(count + len); system.arraycopy(value, offset, value, offset + len, count - offset); str.getchars(value, offset); count += len; return this; }
通过分析这几个方法源码,我们可以看到,stringbuilder和stringbuffer在方法的实现上是一致的,唯一的区别是stringbuffer的所有方法都加了synchronized锁,所以是线程安全的
string tostring()把stringbuffer转换成字符串
@override public synchronized string tostring() { if (tostringcache == null) { tostringcache = arrays.copyofrange(value, 0, count); } return new string(tostringcache, true); }
stringbuffer与stringbuilder都是在修改的时候并没有产生新的对象,只是在调用tostring方法是才转换为字符串。
总结
- stringbuilder和stringbuffer的类结构是一致的,都是使用父类的char数组保存字符。
- stringbuffer的所有方法都加了synchronized锁,所以是线程安全的,但是这也使得它的效率比stringbuilder低。
- stringbuilder和stringbuffer的基本思想是一致的,对stringbuilder、stringbuffer的任何修改都不会产生新对象,这也使得stringbuilder、stringbuffer在进行大量拼串截取时比string的效率高。
推荐阅读
-
Java中对象的比较操作实例分析
-
代码静态分析工具比较(软件开发流程八个步骤)
-
Oracle In和exists not in和not exists的比较分析
-
AndroidManifest.xml
和 分析及比较 -
String、StringBuffer和StringBuilder类的区别
-
全面解释java中StringBuilder、StringBuffer、String类之间的关系
-
Oracle date如何比较大小分析
-
详解.NET中string与StringBuilder在字符串拼接功能上的比较
-
Java中String、StringBuffer、StringBuilder的区别(转)
-
PHP中strcmp()和strcasecmp()函数字符串比较用法分析