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方法是才转换为字符串。

总结

  1. StringBuilder和StringBuffer的类结构是一致的,都是使用父类的char数组保存字符。
  2. StringBuffer的所有方法都加了synchronized锁,所以是线程安全的,但是这也使得它的效率比StringBuilder低。
  3. StringBuilder和StringBuffer的基本思想是一致的,对StringBuilder、StringBuffer的任何修改都不会产生新对象,这也使得StringBuilder、StringBuffer在进行大量拼串截取时比String的效率高。

StringBuilder、StringBuffer分析比较的更多相关文章

  1. [面试]StringBuilder StringBuffer源码粘贴(并非源码分析, 请绕道)

    StringBuilder StringBuffer 源码 这里只是我个人笔记, 并没有在这篇文章里做任何技术分享, 请同学们绕道- -.如果需要我会后期补上的..... 本来是想分析源码来着, 但是 ...

  2. JDK源码分析系列---String,StringBuilder,StringBuffer

    JDK源码分析系列---String,StringBuilder,StringBuffer 1.String public final class String implements java.io. ...

  3. stringbuffer与stringbuilder区别分析

    它们到底都有什么区别呢! 三者都是用来对字符串进行操作,String通常用来定义一个变量,而StringBuilder StringBuffer则通常用来对字符串进行拼接等操作.但其实String同样 ...

  4. string,stringbuilder,stringbuffer用法

    总结:1.如果要操作少量的数据用 = String   ==================================>字符串常量2.单线程操作字符串缓冲区 下操作大量数据 = Strin ...

  5. 深入源码剖析String,StringBuilder,StringBuffer

    [String,StringBuffer,StringBulider] 深入源码剖析String,StringBuilder,StringBuffer [作者:高瑞林] [博客地址]http://ww ...

  6. String&StringBuilder&StringBuffer总结

    一.String的JVM内存分配测试与分析           String a="a"; String b="b"; String c="ab&qu ...

  7. 数据结构(逻辑结构,物理结构,特点) C#多线程编程的同步也线程安全 C#多线程编程笔记 String 与 StringBuilder (StringBuffer) 数据结构与算法-初体验(极客专栏)

    数据结构(逻辑结构,物理结构,特点) 一.数据的逻辑结构:指反映数据元素之间的逻辑关系的数据结构,其中的逻辑关系是指数据元素之间的前后件关系,而与他们在计算机中的存储位置无关.逻辑结构包括: 集合 数 ...

  8. [java] StringBuilder / StringBuffer / String 建立字符串

    1.三者在建立新字符串速度方面的比较: StringBuilder >  StringBuffer  >  String 2.线程安全性: StringBuilder:线程非安全的 Str ...

  9. JAVA StringBuilder StringBuffer String比较

    字符串连接时的效率: StringBuilder>StringBuffer>String 区别: StringBuilder效率最高,但是不是线程安全的,适用于单线程.多线程用String ...

随机推荐

  1. Codeforces Round #627 (Div. 3)

    1324A - Yet Another Tetris Problem(思维) 题意 给一个数组,每一个数组中的元素大小表示在竖直方向的方块数量,元素相邻怎竖直方向的方块也相邻,类似于俄罗斯方块当底层被 ...

  2. 微信小程序wx:for隐藏遍历的最后一个元素

    微信小程序开发时有时会需要从wx:for遍历的元素中选取最后一个来进行相关操作,以下方法以隐藏最后一个元素为例 index==list.length-1 通过获取列表的总长度减一来得到最后一个元素是最 ...

  3. Vulnhub DC-4靶机渗透

    信息搜集 nmap -sP 192.168.146.0/24 #扫网段看看存活的主机,找到靶机 nmap -sS -Pn -A 192.168.146.141 可以看到开放了22和80端口,那么就可以 ...

  4. python10

     一.多进程multiprocessing multiprocessing包是Python中的多进程管理包.与threading.Thread类似,它可以利用multiprocessing.Proce ...

  5. json格式的文件操作2

    1.字典转换为字符串(json.dumps) jsongeshi={"name":"yajuan","age":"10" ...

  6. 力软敏捷框架集成布局插件(ce-layout)

    最近用力软的框架觉得框架在布局这块不是很友好特别是对像css不是很好的程序员来说,大部分大家都是后端程序员. 所以决定集成一个和力软敏捷框架风格比较一致的布局插件进来 插件ce-layout ,下载地 ...

  7. Linux c++ vim环境搭建系列(6)——CMakeLists.txt多文档多目录组织方法和编写示例

    CMakeLists.txt学习 1. 概要 主要是关于cmakelists.txt的编写模板,和多文档多目录的组织方法详解, 涉及第三方库的添加使用方法. 这里主要介绍cmakelists.txt的 ...

  8. Linux常用命令02(远程管理)

    01 关机/重启 序号 命令 对应英文 作用 01 shutdown 选项 时间 shutdown 关机/重新启动 1.1 shutdown shutdown 命令可以 安全 关闭 或者 重新启动系统 ...

  9. 2020不平凡的90天,Python分析三个月微博热搜数据带你回顾

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:刘早起早起 PS:如有需要Python学习资料的小伙伴可以加点击下方链 ...

  10. ASE课程总结 by 朱玉影

    收获: 最大的收获应该就是对待选题要慎重吧,虽然前期做了一下调研,但是还是不够,所以到最后我们的项目才会不能公开发布,项目中间也是波折不断,导致我们走了很多弯路,浪费了很多时间吧.选题一定要慎重,慎重 ...