打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
面试官:说说这段代码存在什么问题?
userphoto

2022.08.02 广东

关注

《Java开发手册》是阿里巴巴集团技术团队的经验总结,经历了多次不断实战的检验及不断完善,公开到业界后,众多社区开发者踊跃参与,共同打磨完善,系统化地整理成册。

手册的愿景是码出高效,编程高质量的程序。

字符串处理看似简单,却在面试中层出不穷。做出来关于字符串的题目简单,能够完全准确地写出来并不容易。

笔者有次面试时,面试官就问了这样一个问题,说说这段代码存在什么问题?

String str = "start";
for(int i=0; i<100; i++){
  str = str + "hello";
}

这个问题其实关于循环体内的字符串连接方式使用 StringBuilder的append方法进行拓展。

在《Java开发手册》就有提到,值得留意。

阿里原话:

【推荐】循环体内,字符串的连接方式,请使用 StringBuilder 的 append 方法进行扩展。

说明:因为反编译出的字节码文件显示每次循环都会 new 出一个 StringBuilder 对象,然后进行append 操作,最后通过 toString 方法返回 String 对象,造成内存资源浪费。

大概意思是用StringBuilder连接字符串性能要比 String + 的方式要好,因为占用内存资源更少。

要怎么才能更加直观的得知循环体内的字符串连接方式使用String+性能低呢?对此我们可以尝试用时间开销来对比。

    long begTime = System.currentTimeMillis();
    StringBuilder sb = new StringBuilder("start");
    for (int i = 0;i < 10000; i++){
        sb.append(i);
    }
    long endTime = System.currentTimeMillis();
    long time = endTime - begTime;
    System.out.println("StringBuilder消耗时间:" + time);


    String str = "start";
    long begTime2 = System.currentTimeMillis();
    for (int i = 0;i < 10000; i++){
        str = str + i;
    }
    long endTime2 = System.currentTimeMillis();
    long time2 = endTime2 - begTime2;
    System.out.println("String消耗时间:" + time2);

多次输出:

StringBuilder消耗时间:3

String消耗时间:404

StringBuilder消耗时间:2

String消耗时间:481

StringBuilder消耗时间:4

String消耗时间:507

在时间方面,String消耗的时间确实比StringBuilder多得多。

对比 String 与 StirngBuilder 的源码。

String源码

private final char value[];
// 本质是字符数组常量,所以不可变
public String() {
    this.value = "".value;
}

StringBuilder

 public StringBuilder() {
    // StringBuilder 类继承 AbstractStringBuilder 抽象类
    // 创建长度 16 的字符数组
    super(16);
}
// 字符串拼接
public StringBuilder(String str) {
    super(str.length() + 16);
    append(str);
}

AbstractStringBuilder

  AbstractStringBuilder(int capacity) {
    value = new char[capacity];
}

总结

字符串拼接,虽然字符串是不可变的,但还是可以通过新建字符串的方式来进行字符串的拼接。

常用的字符串拼接方式有以下几种方式

  • String+

  • concat

  • StringBuilder

  • StringBuffer

  • StringUtils.join

由于字符串拼接过程中会创建新的对象,所以如果要在一个循环体中进行字符串拼接,就要考虑效率问题和内存问题。

建议优先使用StringBuilder,但不是在循环体中进行字符串拼接的话,直接使用+就好了。

但要是在并发场景中进行字符串拼接的话,就要使用StringBuffer来代替StringBuilder。因为StringBuffer是线程安全的。

StringBuilder和StringBuffer有什么区别?具体分析请戳 这里

由于笔者水平有限,文中纰漏之处在所难免,权当抛砖引玉,不妥之处,请大家批评指正。


作者:洪生鹏  擅长java、Android、qt、小程序平台开发。技术交流、媒体合作、品牌宣传请添加微信: hsp-88ios
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
C#拼接string字符串
java中String类、StringBuilder类和StringBuffer类详解
java教程分享+号与append的效率问题
java提高篇(十四)-----字符串
String、StringBuffer、StringBuilder源码解析
String, StringBuffer, StringBuilder区别
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服