《Java》String、StringBuffer、StringBuilder有什么区别?

目录

String

StringBuffer

StringBuilder

总结


ps:昨天在讨论完String的不可变性之后突然想要做一份总结笔记,总结一下String、StringBuffer、StringBuilder的区别


String

        String是Java中的基础类,提供了各种构造和对字符串的基本操作,并且因为它的不可变性,对于字符串的拼接、截取字符串等操作,都会产生新的String对象,由于字符串操作的普遍性,所以相关的操作的效率往往对程序的性能有明显影响;

那么明显在哪里呢?我们来做一个实验,我们首先创建一个简单的字符串,如果要将字符串进行凭接起来,我们来观察一下,以下代码是凭接1000个字符后的运行时间

 public static void main (String[] args) {
        String str=new String("1~1000的数字有:");
        long time=System.currentTimeMillis();
        for (int i = 1 ; i <= 1000 ; i++) {
            str+=i;
        }
        long lasttime=System.currentTimeMillis();
        System.out.println(lasttime-time);
    }

 

 我们可以看到运行时间为5毫秒,我们再用测试一下1w个数据

public static void main (String[] args) {
        String str=new String("1~1_0000的数字有:");
        long time=System.currentTimeMillis();
        for (int i = 1 ; i <= 1_0000 ; i++) {
            str+=i;
        }
        long lasttime=System.currentTimeMillis();
        System.out.println(lasttime-time);
    }

 

 我们可以看到,稍等了一会儿才出来,博主又测试了一下10_0000个数据,需要用的时间为20秒左右

我们可以发现,数据拼接的越长需要的时间越长,这是为什么呢?

        我们String凭接的时候会产生大量的常量,首先是凭接前我们会产生一个常量,拼接后又会重新产生一个常量, 如此反反复复进行开辟,既造成了大量的内存浪费,大量的时间也被浪费掉了,不停的创建对象是程序低效的一个重要原因。那么相同的字符串值能否在堆中只创建一个String对象那。显然拘留字符串能够做到这一点,除了程序中的字符串常量会被JVM自动创建拘留字符串之外,调用String的intern()方法也能做到这一点。当调用intern()时,如果常量池中已经有了当前String的值,那么返回这个常量指向拘留对象的地址。如果没有,则将String值加入常量池中,并创建一个新的拘留字符串对象。

这边也有一个反编译的解读,打开方式如下,首先找到class文件所在的位置

 

 解读大概如下

那么我们对于这种行为有什么更好的解决方法吗?

此时我们就诞生了StringBuffer、Stringbuilder 


StringBuffer

StringBuffer是为解决上面提到拼接产生太多中间对象的问题而提供的一个类,我们可以用 append 或者 add 方法,把字符串添加到已有序列的末尾或者指定位置。本质是一个线程安全的可修改字符序列,它保证了线程安全(不会常见常量)

我们可以来看一下StringBuffer的源码 

 大部分方法都是sychronized(英译同步进行)所修饰的,保证线程安全

那么有的童鞋就疑惑了,什么是线程安全呢?下面用一张图解读 

今天我们帅气的博主在公共卫生间上厕所,然后我们如果将卫生间门锁起来,别人就不会再进来了,但是如果我不去将们锁起来,别人在不知道情况下就会推门而进……线程安全就是那把锁,我们上锁以及开锁也是需要时间的,但是能保证厕所一次只会容纳一个人,也就是只有一个进程在运行,如此就是线程安全 

虽然StringBuffer可以保证线程安全,但也随之带来了额外的性能开销,所以除非有线程安全的需要,不然还是推荐使用它的后继者,也就是 StringBuilder


StringBuilder

 StringBuilder是 Java 1.5 中新增的,在能力上和StringBuffer没有本质区别,但是它去掉了线程安全的部分,有效减小了开销,是绝大部分情况下进行字符串拼接的首选。  

还是可以观察一下源码


总结

(1)如果要操作少量的数据用 String;

(2)多线程操作字符串缓冲区下操作大量数据 StringBuffer;

(3)单线程操作字符串缓冲区下操作大量数据 StringBuilder

StringBuffer和StringBuilder的区别 

        StringBuffer是在保证线程安全的环境下运行的,相比更加的安全,StringBuilder不会考虑线程安全的问题,但是运行速度>StringBuffer,毕竟加锁和解锁也是需要时间的嘛

猜你喜欢

转载自blog.csdn.net/m0_69996872/article/details/128364646