查看原文
其他

面试官:String、StringBuiler、StringBuffer,谁性能最高?

点击蓝字关注☞ 面试专栏 2021-08-29

关注公众号“面试专栏”,回复面试,获取优质面试资源。

面试专栏:第1-20期文章汇总

本篇是1000期面试系列文章的第63篇,持续更新中.....欢迎关注。

 一、前言

刚开始学习Java时,作为只会C语言的小白,就为其中的字符串操作而感到震撼。相比之下,C语言在字节数组中保存一个结尾的\0去表示字符串,想实现字符串拼接,还需要调用strcpy库函数或者自己手动去复制数组,非常麻烦,更别提其他复杂操作,而Java通过String类让字符串操作变得十分简单和方便。

除此之外,还有stringbuilder等这些类的辅助,那么本文就从String,StringBuiler和StringBuffer的区别开始,去探讨Java中的字符串操作。

二、String,StringBuiler和StringBuffer

2.1 String类

Java 提供了 String 类来创建和操作字符串。在源码中可以看到,String类内部的实现也是一个字节数组,这个数组是final类型的,因此String是不可变的对象,每次在对String类进行改变的时候都会生成一个新的string对象,然后将指针指向新的string对象。

2.2 StringBuiler 类

和 String 类不同的是,StringBuilder 类的对象能够被多次的修改,并且不产生新的对象。这个特性的意义在于,如果我们进行大量的字符串操作,使用String类就会产生很大的性能消耗,而StringBuilder就可以避免这个问题。

2.3 StringBuffer 类

StringBuffer 和StringBuiler之间的最大不同在于 StringBuilder 的方法不是线程安全的

由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。

2.4 String,StringBuiler和StringBuffer的比较(对比C/C++)

三、各种字符串操作的效率测试

3.1 测试代码

@Test
public void test() {
        int count = 100000;

        long startTime = System.currentTimeMillis();
        String str = "";
        for(int i = 0; i< count; i++){
            str += i;
        }
        System.out.println("执行"+count+"次  String 耗时:"+ getRunTime(startTime));

        startTime = System.currentTimeMillis();
        StringBuilder stringBuilder = new StringBuilder("");
        for (int i = 0; i < count; i++) {
            stringBuilder.append(i);
        }
        System.out.println("执行"+count+"次  StringBuilder 耗时:"+ getRunTime(startTime));

        startTime = System.currentTimeMillis();
        StringBuffer stringBuffer = new StringBuffer("");
        for (int i = 0; i < count; i++) {
            stringBuffer.append(i);
        }
        System.out.println("执行"+count+"次  StringBuffer 耗时:"+ getRunTime(startTime));

}

3.2 测试结果

执行100000次  String 耗时:32s
执行100000次  StringBuilder 耗时:2ms
执行100000次  StringBuffer 耗时:4ms

3.3 小结

可以看到String类的性能远低于StringBuiler和StringBuffer,而StringBuiler在本次测试中比Stringbuffer提高了50%的性能

四、Java字符串和正则表达式

4.1 测试代码

@Test
public void test0(){
        //邮政编码
        String postCode = "[1-9]\\d{5}";
        //区号-座机号码
        String areaCode = "\\d{3}-\\d{8}|\\d{4}-\\d{7}";
        //手机号码
        String phone = "(?:13\\d|15\\d|18\\d)\\d{5}(\\d{3}|\\*{3})";

        String text = "邮政编码:440834"+
                      "区号-座机号码: 020-12345678"+
                      "手机号:13536373839"+
                      "邮政编码:440833"+
                      "区号-座机号码: 010-12345678"+
                      "手机号:13536373739";

        Pattern p = Pattern.compile(postCode);
        Matcher m = p.matcher(text);
        System.out.println("文本中包含邮政编码:");
        while (m.find()){
            System.out.println(m.group());
        }

        p = Pattern.compile(areaCode);
        m= p.matcher(text);
        System.out.println("文本中包含区号-座机号码:");
        while (m.find()){
            System.out.println(m.group());
        }

        p = Pattern.compile(phone);
        m= p.matcher(text);
        System.out.println("文本中包含手机号:");
        while (m.find()){
            System.out.println(m.group());
        }
}

4.2 测试结果

文本中包含邮政编码:
440834
123456
135363
440833
123456
135363
文本中包含区号-座机号码:
020-12345678
010-12345678
文本中包含手机号:
13536373839
13536373739

五、总结

经过测试和比较,可以看到Java中同为字符串操作,但由于背后实现的原理不同,形成的性能差异也是十分巨大,相比之下,C/C++中的字符串操作性能更高。String类的性能远低于StringBuiler和StringBuffer,而StringBuiler比Stringbuffer的性能稍微高一点。

对性能的探究,最终还是要回到使用场景,可以总结得出:

  • 如果不涉及字符串操作,那么String类是首选
  • 如果涉及的字符串操作没有线程安全问题,那么使用StringBuilder
  • 如果涉及的字符串操作存在线程安全问题,那么使用StringBuffer。

好了,今天分享就到此,期待你的关注喔!

来源:uo5jl.cn/7UfLf

精彩推荐

面试官:谈谈内存泄漏和内存溢出的联系与区别

面试官:说说一个 Java 对象有多大?

面试官:项目中有用过多线程吗?

后端开发必备书

    : . Video Mini Program Like ,轻点两下取消赞 Wow ,轻点两下取消在看

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存