String,StringBuilder,StringBuffer源码分析

String,StringBuilder,StringBuffer源码分析在Java中,对于字符串的操作有这三种:String、StringBuilder、StringBuffer。这三者的效率是:StringBuilder StringBuffer String。 先来看下String的源码,如图所示: 从图中我们可以看出,String是有…

声明:本文使用JDK1.8

在Java中,对于字符串的操作有这三种:String、StringBuilder、StringBuffer。这三者的效率是:StringBuilder > StringBuffer > String。

String a = "abc";
a = a + "d";
System.out.println(a);
StringBuffer buffer = new StringBuffer();
buffer.append("a");
System.out.println(buffer);
StringBuilder builder = new StringBuilder();
builder.append("b");
System.out.println(builder);

String

先来看下String的源码,如图所示:

String,StringBuilder,StringBuffer源码分析

从图中我们可以看出,String 是由 char 数组构成的,而且有 final 关键字修饰,这说明 String 类型的对象是不可以改变的。那么,平时我们使用“+”来拼接字符串是什么实现的?

如上面的代码,首先创建一个 String 对象 a,再把“abc”赋值给它,后面Java虚拟机又创建了一个 String 对象 a,然后再把原来的 a 的值和 “d” 加起来再赋值给新的 a,而原来的a 就会被Java虚拟机的垃圾回收机制(GC)给回收掉了,所以,a 实际上并没有被更改,也就是前面说的 String 对象一旦创建之后就不可更改了。从这里可以看出,对于频繁操作的字符串,不建议使用 String 类型,这将会是一个不断创建新的对象并且将旧的对象回收的一个过程,所以执行速度很慢。

对于 String 类型对象的“+”操作,通过在 StringBuilder 的 append 方法上面打断点,可以发现对于String的操作,其实是使用了 StringBuilderappend 操作,这个也是线程安全。详细可以看下面关于 StringBuilder 的源码。

String,StringBuilder,StringBuffer源码分析

String,StringBuilder,StringBuffer源码分析

String 的性能差,主要是对于频繁操作的字符串,不断的创建和销毁对象,对于程序性能有很大的影响。

StringBuffer

String,StringBuilder,StringBuffer源码分析

从源码中我们可以看出,对 StringBuffer 来说,底层也是 char 数组。StringBuffer 默认初始空间是16。对于 StringBuffer 的扩容,从下面的这张图上面可以看出,是在旧的数组的2倍上面,再加2进行扩容。

String,StringBuilder,StringBuffer源码分析

下面我们在来看下 StringBuffer 的操作函数appendappend 方法是由 synchronized 修饰的,是线程安全的。

String,StringBuilder,StringBuffer源码分析

StringBuilder

通过和 StringBuffer 的源码比较,我们发现,底层也是char数组,初始空间也是16。StringBuilderStringBuffer 都是从 AbstractStringBuilder 继承来的,所以对于其初始空间和扩容都是相同的。

String,StringBuilder,StringBuffer源码分析

对于 StringBuilderStringBuffer 的区别可以从下面的这张图片上看出,对于append()方法,缺少了synchronized 修饰,这使得 StringBuilder 不是一个线程安全。

String,StringBuilder,StringBuffer源码分析

三者性能比较

我做了个测试,代码如下:

public static void main(String[] args) {
    int num = 10000;
    String a = "abc";
    long time = System.currentTimeMillis();
    for (int i = 1; i < num; i++) {
        a = a + i;
    }
    System.out.println(System.currentTimeMillis() - time);
    long time1 = System.currentTimeMillis();
    StringBuffer buffer = new StringBuffer();
    for (int i = 1; i < num; i++) {
        buffer.append(i);
    }
    System.out.println(System.currentTimeMillis() - time1);
    StringBuilder builder = new StringBuilder();
    long time2 = System.currentTimeMillis();
    for (int i = 1; i < num; i++) {
        builder.append(i);
    }
    System.out.println(System.currentTimeMillis() - time2);
}

再来看下运行的结果:

405
1
1

从运行结果,我们可以非常明显的看出这三者的性能比较。

总结

String 长度大小不可变
StringBuffer 和 StringBuilder 长度可变
StringBuffer 线程安全 StringBuilder 线程不安全
因此:
String:适用于少量的字符串操作的情况
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况

今天的文章String,StringBuilder,StringBuffer源码分析分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/16579.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注