为什么 Java 8 中不再需要 StringBuilder 拼接字符串

来源:codeceo 发布时间:2016-12-27 阅读次数:427
 

  在Java开发者中,字符串的拼接占用资源高往往是热议的话题.

  让我们深入讨论一下为什么会占用高资源。

  在Java中,字符串对象是不可变的,意思是它一旦创建,你就无法再改变它。所以在我们拼接字符串的时候,创建了一个新的字符串,旧的被垃圾回收器所标记。

  如果我们处理上百万的字符串,然后,我们就会生成百万的额外字符串被垃圾回收器处理。

  虚拟机底层在拼接字符串时执行了众多操作。拼接字符串最直接的点操作(dot operator)就是String#concat(String)操作。

1
2
3
4
5
6
7
8
9
10
public String concat(String str) {
    int otherLen = str.length();
    if (otherLen == 0) {
        return this;
    }
    int len = value.length;
    char buf[] = Arrays.copyOf(value, len + otherLen);
    str.getChars(buf, len);
    return new String(buf, true);
}
1
2
3
4
5
6
public static char[] copyOf(char[] original, int newLength) {
    char[] copy = new char[newLength];
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}
1
2
3
void getChars(char dst[], int dstBegin) {
    System.arraycopy(value, 0, dst, dstBegin, value.length);
}

  你可以看到一个字符数组被创建,长度则是已有字符和拼接的字符长度之和。然后,它们的值复制到新的字符数组中。最后,用这个字符数组创建一个String对象并返回。

  所以这些操作繁多,如果你计算一下,会发现是O(n^2)的复杂度。

  为了解决这个问题,我们使用StringBuilder类。它就像可变的String类。拼接方法帮助我们避免不必要的复制。它拥有O(n)的复杂度,远远优于O(n^2)。

  然而Java 8默认使用StringBuilder拼接字符串。

  Java 8的文档说明:

为了提高字字符串拼接的性能,Java编译器可以使用StringBuffer类或类似技术,在使用求值表达式时,减少中间String对象的创建。

  Java编译器处理这种情况:

1
2
3
4
5
6
public class StringConcatenateDemo {
  public static void main(String[] args) {
     String str = "Hello ";
     str += "world";
   }
}

上面的代码会被编译成如下字节码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class StringConcatenateDemo {
  public StringConcatenateDemo();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return
  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String Hello
       2: astore_1
       3: new           #3                  // class java/lang/StringBuilder
       6: dup
       7: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
      10: aload_1
      11: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      14: ldc           #6                  // String world
      16: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      19: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      22: astore_1
      23: return
}

  你可以在这些字节码中看到,使用了StringBuilder。所以我们在Java 8中不再需要使用StringBuilder类。

为什么 Java 8 中不再需要 StringBuilder 拼接字符串的更多相关文章

  1. 源码上看 .NET 中 StringBuilder 拼接字符串的实现

    前几天写了一篇StringBuilder与TextWriter二者之间区别的文章(链接).当时提了一句没有找到相关源码,于是随后有很多热心人士给出了相关的源码链接(链接),感谢大家.这几天抽了点时间查 ...

  2. 2、Java应用中常见的JDBC连接字符串(SQLite、MySQL、Oracle、Sybase、SQLServer、DB2)

    2.Java应用中常见的JDBC连接字符串 Java应用中连接数据库是不可或缺的,于是便整理一些可能用到的JDBC的jar包及其相匹配的URL,以备日后查阅. 1)SQLite Class.forNa ...

  3. java以逗号为分割符拼接字符串的技巧

    java以逗号为分割符拼接字符串的技巧   答: 不用那么多if判断,让人思维混乱,直接到最后使用deleteCharAt方法去除最后一个逗号即可. 实现代码如下所示: StringBuffer sb ...

  4. 【JVM】Java 8 中的常量池、字符串池、包装类对象池

    1 - 引言 2 - 常量池 2.1 你真的懂 Java的“字面量”和“常量”吗? 2.2 常量和静态/运行时常量池有什么关系?什么是常量池? 2.3 字节码下的常量池以及常量池的加载机制 2.4 是 ...

  5. C# 拼接字符串的几种方式和性能

    开发过程中常用到的拼接字符串的方法有三种: 1 简单 “+=” 拼接法 1 2 3 4 5 string str="a";   str+="c"+"d ...

  6. 昨天还在for循环里写加号拼接字符串的那个同事,今天已经不在了

    引言 都说 StringBuilder 在处理字符串拼接上效率要强于 String,但有时候我们的理解可能会存在一定的偏差.最近我在测试数据导入效率的时候就发现我以前对 StringBuilder 的 ...

  7. 从源代码的角度聊聊java中StringBuffer、StringBuilder、String中的字符串拼接

    长久以来,我们被教导字符串的连接最好用StringBuffer.StringBuilder,但是我们却不知道这两者之间的区别.跟字符串相关的一些方法中总是有CharSequence.StringBuf ...

  8. Java基础学习总结(65)——Java中的String,StringBuilder和StringBuffer比较

    字符串,就是一系列字符的集合. Java里面提供了String,StringBuffer和StringBuilder三个类来封装字符串,其中StringBuilder类是到jdk 1.5才新增的.字符 ...

  9. Java 8中字符串拼接新姿势:StringJoiner

    介绍 StringJoiner是java.util包中的一个类,用于构造一个由分隔符分隔的字符序列(可选),并且可以从提供的前缀开始并以提供的后缀结尾.虽然这也可以在StringBuilder类的帮助 ...

随机推荐

  1. Java基础学习 -- I/O系统、流

    Java类库里有四个表示流的抽象父类:InputStream.OutputStream.Reader.Writer. 其中 InputStream 和 OutputStream 是对字节进行操作的输入 ...

  2. iOS 支付宝的使用

    支付宝相关资源下载地址:支付宝开放平台  在移动支付功能处下载. 一.使用官方的Demo 需要配置基本信息: 打开“APViewController.m”文件,对以下三个参数进行编辑. 二.集成支付宝 ...

  3. SharePoint 2013 新建网站集图解

    前言:接触SharePoint的人可能是越来越多,但是很多人一接触就很迷茫,在技术群里问如何新建网站集,这样一篇图解,帮助新手学习在搭建好SharePoint环境之后,如何创建一个网站集,做一个基本的 ...

  4. AFNetworking的理解

    AFNetworking的理解 使用方法 1. 新建的工程中导入AFNetworking3.0中的(AFNetworking 和UIKit+AFNetworking两个文件夹) 2. 在用到AFNet ...

  5. iOS--浅谈iOS沙盒目录

    原文地址:http://blog.csdn.net/wzzvictory/article/details/18269713 出于安全考虑,iOS系统的沙盒机制规定每个应用都只能访问当前沙盒目录下面的文 ...

  6. Wireshark设置interface 时提示“There are no interfaces on which a capture can be done ”

    Wireshark设置interface 时提示“There are no interfaces on which a capture can be done ” 解决方法: 今天在电脑上安装了WIR ...

  7. php面向对象编程 设计模式

    面向对象编程的基本原则: 单一职责:一个类,只需要做好一件事 开放封闭:一个类,应该是可扩展的,而不是可修改的 依赖倒置:一个类,不应该强依赖另一个类.每个类对应另外一个类都是可替换的 配置化:尽可能 ...

  8. Write on ……… failed: 112(failed to retrieve text for this error. Reason: 15105)

    早上检查数据库的备份邮件时,发现一台Microsoft SQL Server 2008 R2 (SP2)数据库的Maintenance Report有错误 在SSMS里面执行Exec YourSQLD ...

  9. SQL SERVER 2012启动失败 because upgrade step 'SSIS_hotfix_install.sql' 失败

    有台数据库服务器(开发服务器),开发人员邮件告诉我,SSMS连接不了这台服务器,远程登录后,发现SQL SERVER的服务停止了,启动服务时报错,服务启动不了.检查错误日志发现下面一些信息 2015- ...

  10. C、C++: 引用、指针、实例、内存模型、namespace

    // HelloWorld.cpp : Defines the entry point for the console application. // #include "stdafx.h& ...