ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

String 与 StringBuffer 的性能差距 和 为什么

2021-07-21 23:59:48  阅读:198  来源: 互联网

标签:String 对象 StringBuffer 毫秒 差距 字符串 连接


String 与 StringBuffer 的性能差距 和 为什么


一、前言

我们日常中经常要操纵字符串。
而操纵一个字符串有许多方法。
例如直接String,或者StringBuffer。
那么这两种方法的差别在哪,又为什么有差别。 这是我们今天要探讨的。

一、性能的差距

在日常,在结果差别不大的情况下,具有决定因素的一般是性能。那么我们就先比较一下它们之间性能的差距。
这里以字符串拼接举例。话不多说上实例。
//生成10位长度的随机字符串
//然后,先使用String的+,连接10000个随机字符串,计算消耗的时间
//然后,再使用StringBuffer连接10000个随机字符串,计算消耗的时间

//创建一个方法,用于获取随机字符串。
    public static String getRandomString(){
        //10位字符对应一个10位长度的随机字符串
        char[] cs = new char[10];
        for (int i = 0;i<cs.length;i++){
            cs[i] = (char)(new Random().nextInt(91)+32);
            //用ASCII码来获取字符(32-122)。
            //Random().nextInt(num)可以获取一个位于[0,num]区间的整数(包括0,不包括num)
        }
        //返回字符串
        return String.valueOf(cs);
    }

    public static void main(String[] args){

        //记录开始时间,方便记录拼接时间
        long time = System.currentTimeMillis();

    	//首先初始化一个字符串
        String str1 = getRandomString();
        for (int i=0;i<10000;i++){
        	//使用String的+拼接
            str1 += getRandomString();
        }
        //记录此方法所用时间(要减去初始时间)
        long time1 = System.currentTimeMillis() - time ;
        System.out.println("使用字符串连接的+方式,连接10000次,耗时" + time1 + "毫秒");

		//初始化字符串
        String str2 = getRandomString();
        //新建StringBuffer
        StringBuffer sb = new StringBuffer(str2);
        for (int i=0;i<10000;i++){
        	//使用StringBuffer的append方法拼接字符串
            sb.append(getRandomString());
        }
        //记录此方法所用时间(同样减去初始时间和上个方法的时间)
        long time2 = System.currentTimeMillis()-time1-time;
        System.out.println("使用StringBuffer的方式,连接10000次,耗时" + time2 + "毫秒");
    }
10000次运行结果
使用字符串连接的+方式,连接10000次,耗时108毫秒
使用StringBuffer的方式,连接10000次,耗时37毫秒

50000次运行结果
使用字符串连接的+方式,连接50000次,耗时4324毫秒
使用StringBuffer的方式,连接50000次,耗时66毫秒

100000次运行结果
使用字符串连接的+方式,连接100000次,耗时8383毫秒
使用StringBuffer的方式,连接100000次,耗时137毫秒


从上面程序的运行结果可以很明显的看出StringBuffer比String快上许多。
那么为什么呢。
(敲黑板)今天的重点来了。

二、性能差距的原因

String

字符串 是一个常量,具有immutable(不可变的)。
也就是说,当你创建了一个字符串后,你只能读,但不能进行任何更改。
那么java是如何对一个已经初始化字符串进行更改的呢?

那么我们就可以换个思路,既然旧的不行,那我们就找个新的。
所以,当你更改一个字符串时。
java先创建了一个新对象,将内容移到新对象那,并且将指针指向新对象。这样你就完成了对字符串的更改。

是不是很好。
但我们是不是忘了什么。
对了,那个旧对象怎么办?
难道就把它留在那吗?
事实上是的。当我们将指针指向新对象后,旧对象就成为了没有家的人(无引用对象)。

那么当我们创建的对象多了后,JVM检测到对象太多了,于是启动了人类清除计划 启动了GC。
那么“男上加男”,新对象的创建 以及 GC的启动,一切都在吞吃你的内存,所以性能便降低了许多。

StringBuffer

看了String的原理,你应该可以发现它的症结所在就是对象的创建。那么想要提高性能,那我们便要减少对象的创建,甚至不需要对象的创建。
那么这时StringBuffer就挺身而出了:我行!

StringBuffer 对象并不是immutable(不可变的),所以它想变多少次就变多少次。但它永远是它,对象没有改变。所以那一部分的内存就可以节约下来了。

这便是StringBuffer那么快的原因(它始终都是那么专一,不像String一样那么多变)

一些建议

1.当频繁操纵一个字符串时,建议使用StringBuffer进行操纵。
2.少量时String,StringBuffer均可。
3.建议尽量不要使用StringBulider,为了那10%的性能提升,而冒着线程不安全的风险,不值得。
StringBulider 没有多线程安全,而StringBuffer有,所以StringBuffer要慢点,但也要安全点。

结语

没啥结语。
有问题放在评论区,若我看到了,会给你尽快回复的。
如果文章内容有什么问题也欢迎指正。

感谢你的阅读。

标签:String,对象,StringBuffer,毫秒,差距,字符串,连接
来源: https://blog.csdn.net/mo7984130/article/details/118976549

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有