专栏首页呼延String Stringbuilder Stringbuffer异同

String Stringbuilder Stringbuffer异同

字符串在编程中使用的非常频繁,同时又是面试中的常见题型,那么我们的对字符串相关类String,StringBuilder,StringBuffer的理解真的正确吗?今天就通过对三个类源码的阅读,来进一步加强理解。

目录

String概述

打开String类的源码,可以发现String类是被final所修饰的,因此String类不可以被继承。

同样的,用来保存值得char数组 value也是被final修饰的,这就可以得出关于String的一个很重要的结论。

String是字符串常量,值是不可改变,通常我们对String的操作都是通过new一个新的String对象来完成的

如下图中的subString方法和replace方法。

StringBuilder和StringBuffer

既然已经有了String这个功能完备的嘞,那么为什么还需要StringBuilder和StringBuffer呢?

让我们来看一下这两个类的源代码:

可以看出,这两个类共同继承于AbstractStringBuilder,那么打开这个类的源码看一下:

可以看到,这个抽象类中也是以char数组的形式来保存字符串,但是,这个数组是可变的,我们看一下append方法的代码:

append()是最常用的方法,它有很多形式的重载。上面是其中一种,用于追加字符串。如果str是null,则会调用appendNull()方法。这个方法其实是追加了’n’、’u’、’l’、’l’这几个字符。如果不是null,则首先扩容,然后调用String的getChars()方法将str追加到value末尾。最后返回对象本身,所以append()可以连续调用。

那么StringBuffer、StringBuilder的区别在哪里呢?

这是StringBuffer的length方法和capacity方法。

这是AbstractStringBuilder的length方法和capacity方法(Stringbuilder没有进行重写)。

很明显,Stringbuffer对大部分方法添加了 synchronized关键字,来保证线程安全。

异同

从上面的一些源码中可以简单分析出String,StringBuilder,StringBuffer的一些异同点,如下:

  • String是常量,不可改变,StringBuffer、StringBuilder是变量,值是可变的
  • StringBuilder是线程不安全的,而StringBuffer线程安全。 String是常量,线程当然安全。

性能比较

说了这么多,在实际应用过程中,到底应该注意点什么呢?

下面来实际测试一下:

public Map<String, Map<String, String>> stringAnalytics() {
    Map<String, Map<String, String>> result = new HashMap<>();
    Map<String, String> time = new HashMap<>();

    long pre = System.currentTimeMillis();
    String s = "";
    for (int i = 0; i < 50000; i++) {
      s += i;
    }
    time.put("String", String.valueOf(System.currentTimeMillis() - pre));

    long preBuilder = System.currentTimeMillis();
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < 50000; i++) {
      sb.append(i);
    }
    time.put("StringBuilder", String.valueOf(System.currentTimeMillis() - preBuilder));

    long preBuffer = System.currentTimeMillis();
    StringBuffer stringBuffer = new StringBuffer();
    for (int i = 0; i < 50000; i++) {
      stringBuffer.append(i);
    }
    time.put("StringBuffer", String.valueOf(System.currentTimeMillis() - preBuffer));

    result.put("time", time);
    System.out.print(result);
    return result;
  }

在上面的代码,分别使用String,StringBuilder,StringBuffer进行了50000的字符串拼接操作(String使用+方法,其他两个类使用append方法),每次拼接的值为当前循环的数字。在该部分执行前后记录当前系统时间,最后算出消耗时间。

得到的结果如下图:

  • String消耗16.153秒
  • StringBuilder消耗0.005秒
  • StringBuffer消耗0.013秒

结论

终于到了喜闻乐见的结论时候:

PS:以下结论使用于大部分情况,实际编译编码过程中会有编译优化等原因稍微影响结论,但不能代表大多数。

1.当字符串改动较小的时候,使用String 原因:方便且线程安全

2.当字符串需要频繁进行改动,且单线程使用StringBuilder 原因:由5中可知,StringBuilder是效率最高的了。

3.当字符串需要频繁改动,且多线程调用。使用StringBuffer 原因:StringBuffer中添加了对多线程应用时的保护,可以保证线程安全,且性能下降并不严重,在可接受范围内。

ChangeLog

2018-09-22 完成

以上皆为个人所思所得,如有错误欢迎评论区指正。

欢迎转载,烦请署名并保留原文链接。

联系邮箱:huyanshi2580@gmail.com

更多学习笔记见个人博客——>呼延十

var gitment = new Gitment({ id: 'String Stringbuilder Stringbuffer异同', // 可选。默认为 location.href owner: 'hublanker', repo: 'blog', oauth: { client_id: '2297651c181f632a31db', client_secret: 'a62f60d8da404586acc965a2ba6a6da9f053703b', }, }) gitment.render('container')



本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Guava中的一些增强集合类

    写了好多和Java集合类有关的文章,学习了好多集合类的用法,有没有感觉还是有一些常见的需求集合类没有办法满足呢?需要自己使用Java集合中的类去实现,但是这种常...

    呼延十
  • 类似微博等社交软件中用户关注关系的存储实现方案遐想

    本文主要对设计方案进行一些思考及测试,思考结果的正确性无法保证,测试结果保证正确.

    呼延十
  • 构建器builder模式以及lombok的介绍及使用

    假设某个类,现在有3个必选属性,有5个可选属性.(为了代码简洁,后面都只写一个必选属性,2个可选属性.懂就行).

    呼延十
  • 【JAVA】java字符串拼接

    后端技术漫谈
  • 【趣学程序】java常用类(一)

    String表示字符串,所谓字符串,就是一连串的字符,是java中最常用的类之一。 String是不可变类,一旦String对象被创建,包含在对象中的字符序列(...

    趣学程序-shaofeer
  • httpclient爬虫爬取汉字拼音等信息

    下面是使用httpclient爬虫爬取某个网站的汉字相关信息的实践代码,中间遇到了一些字符格式的问题。之前被同事见过用html解析类来抓取页面信息,而不是像我现...

    FunTester
  • 线程安全的Map的小Demo

    Dream城堡
  • Java开发者如何正确的使用String,StringBuffer,StringBuilder类

    通过前面的文章,我们知道String类最大的特点是不可变性,这意味着对String类的任何修改都会新生成一个字符串,比如你执行了String类的substrin...

    我是攻城师
  • 注册中心 Eureka 源码解析 —— StringCache

    看起来一切都非常非常非常美好,那为什么 Eureka 自己实现了 StringCache ?

    芋道源码
  • Spark Tips3: 在Spark Streaming job中读取Kafka messages及其offsetRange

    在Spark Streaming job中读取Kafka topic(s)中的messages时,有时我们会需要同步记录下每次读取的messages的offse...

    叶锦鲤

扫码关注云+社区

领取腾讯云代金券