Java字符串拼接的优雅方式实例详解

目录
  • 背景
  • String底层原理
  • 拼接的方法
    • 经典但有时不优雅的 +
      • 优点
    • 缺点
      • 业务一
    • 万能的StringBuilder
    • 线程安全的StringBuffer
    • 灵活的String.format()
    • 有点绿色的concat
    • JDK1.8优雅写法
    • 经典的Guava
  • 总结

背景

字符串拼接不管是在业务上,还是写算法时都会频繁使用到。对于Java来说,字符串拼接有着很多种方式,他们之间的区别是什么,对应不同的业务哪种更好用呢。

String底层原理

在讨论字符串拼接时,首先需要知道String的底层原理。

我们这里只讨论jdk1.8之后的情况,看下结构

private final byte[] value;

这一行代码已经可以说明很多东西。字符串实质就是不可变的byte数组。因为不可变,所以对他进行拼接对他拼接实际就是生成了多个对象,这就是不鼓励对字符串进行拼接的原因。但不可变也有很多好处,例如线程安全、可以存在字符串缓冲池复用字符串等。

拼接的方法

经典但有时不优雅的 +

String a = "123";
String b = "456";
String c = a + b;

c这个字符串就是ab拼接起来的字符串,“123456”

这段代码反编译出来的代码是

String c = (new StringBuilder()).append(a).append(b).toString();
​

可以看出这个 + 是Java的语法糖,他实际上是调用的StringBuilder,通过append()来进行拼接。关于StringBuilder我们后面再讲,先来讲下这个用法的优缺点。

优点

“+”,最大的优点就是简洁。如果两个字符串需要首尾拼接,+号义不容辞的成为了最好的使用方式。

缺点

说到缺点的话就多了。简洁也是他的最大缺点,也就是不够灵活。

业务一

有一个字符串List,我需要把他们拼接起来,怎么办?

for(String tmp:list){
    s += tmp;
}

简洁的一批,但是他隐藏着很大的问题!

上面说到这种拼接方式实际是通过StringBuilder的append的方法。你不需要知道他的原理,你只需要知道,每次循环,他都会new一个StringBuilder对象。创建对象的开销是很大的,如果List有几千几万,内存开销和时间开销是不能接受的!

所以阿里巴巴的规范说到:

表面上是推荐,实际就是禁止。写算法会消耗大量时间导致不通过,业务也会因为这种方式提高了无故的开销,属于领导看了想打死的代码。

业务二

大家好,我叫XX,我是来自XXX学校的大X学生,我的爱好是XXX。

一个经典的模板,我需要替换掉中间的XXX为controller的参数,怎么办呢?

String s = "大家好,我叫"+name+"我是来自"+school+"学校的大"+num+“学生,我的爱好是”+aihao;

属于可用但极其丑陋的代码。如果其他接口也需要这个模板,我还要把这段话复制到所有位置上吗?如果我要改动这个,我要对所有代码进行改动吗。

万能的StringBuilder

先介绍下StringBuilder的原理。把字符串拼接想象成数组就很好理解了,StringBuilder有点类似于ArrayList,可变数组。

    /**
     * The value is used for character storage.
     */
    char[] value;

区别就是没有final修饰,当到达阈值时进行扩容操作。append方法就是往后插入。

那么就可以解决上面业务一的问题了。

StringBuilder sb = new StringBuilder();
for(String tmp:list){
    sb.append(tmp);
}
String s = sb.tostring();

相比于上面,只创建了一个StringBuilder对象,减少循环创建的开销。

线程安全的StringBuffer

StringBuffer与StringBuilder相比,有线程安全的优势,通过上锁的方式。同时导致效率略低于StringBuilder。

灵活的String.format()

这个严格来说应该叫做格式化,但也可以用来拼接。

熟悉c语言的应该能够懂,我这里举一个例子

String msg = String.format(“我是%s小学的学生,我爱吃%s”,"阳光","屎");
//输出 我是阳光小学的学生,我爱吃屎

使用字符串链代替%s,生成需要的字符串。也不仅可以拼接字符串,可以看下下图(偷的图,没全部验证过,错了别找我)

这种方式就解决了业务二的问题。通过编写枚举或者常量字符串留出对应的位置,使用时再用String.format()拼接。

有点绿色的concat

为什么说他绿色呢,就是我还没有找到他有什么优势。

String s = "123".concat("456");
//结果等价于
String s = "123" + "456";

concat方法的原理是数组扩容后复制之前的内容并写新的内容,和StringBuilder底层有点相像。

但是相比于“+”号来说,既不简便,又没有什么效率上的提高。在循环字符串拼接的条件,效率上会略有一点优势,但是这种情况是根本不被允许的,所以concat就很鸡肋。

JDK1.8优雅写法

刚才提到业务一的解决办法可以使用朴素的StringBuilder来解决,但是对于业务代码来说有一点冗长。
Jdk1.8给出了优雅的答案

String s = String.join("_", list);

一行代码,就可以把list里的字符串通过“_”拼接起来。

经典的Guava

guava是我们crud程序员的好伙伴,这里就不用多说了。我们最常接触到的其实就是guava的本地缓存和字符串操作。

String result = Joiner.on(",").join(list);

也是简洁的一句话,但是相比于jdk本土的字符串方法来说,他还有一些其他的特性。例如可以把为null的数组给跳过或者替换掉等等。功能要比jdk的要丰富一点。在正常的web项目里基本都会有Guava的依赖,使用起来还是很方便的。

总结

这篇文章偏重于代码编写方面,如何写出简洁高效的代码,是我们要追求的。不要让你写的垃圾代码恶心到接手的同事就好了。

到此这篇关于Java字符串拼接的优雅方式的文章就介绍到这了,更多相关Java字符串拼接内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • java字符串拼接与性能分析详解

    假设有一个字符串,我们将对这个字符串做大量循环拼接操作,使用"+"的话将得到最低的性能.但是究竟这个性能有多差?如果我们同时也把StringBuffer,StringBuilder或String.concat()放入性能测试中,结果又会如何呢?本文将会就这些问题给出一个答案! 我们将使用Per4j来计算性能,因为这个工具可以给我们一个完整的性能指标集合,比如最小,最大耗时,统计时间段的标准偏差等.在测试代码中,为了得到一个准确的标准偏差值,我们将执行20个拼接"*"

  • Java 字符串拼接竟然有这么多姿势(收藏版)

    但扪心自问,在我做程序员的前两年内,我也不知道为啥.遇到字符串拼接就上"+"号操作符,甭管是不是在循环体内.和小菜比起来,我当时可没他这么幸运,还有一位热心的"二哥"能够分享这份价值连城的开发手册. 既然我这么热心分享,不如好人做到底,对不对?我就认认真真地写一篇文章,给小菜解惑一下. 01."+"号操作符 要说姿势,"+"号操作符必须是字符串拼接最常用的一种了,没有之一. String chenmo = "沉默&q

  • Java 字符串的拼接详解

    工作日忙于项目的逻辑实现,周六有点时间,从书柜里拿出厚厚的英文版Thinking In Java,读到了字符串对象的拼接.参考着这本书做个翻译,加上自己思考的东西,写上这篇文章记录一下. 不可变的String对象 在Java中,String对象是不可变的(Immutable).在代码中,可以创建多个某一个String对象的别名.但是这些别名都是的引用是相同的. 比如s1和s2都是"droidyue.com"对象的别名,别名保存着到真实对象的引用.所以s1 = s2 String s1

  • JAVA字符串拼接常见方法汇总

    字符串的拼接,常使用到的大概有4种方式: 1.直接使用"+"号 2.使用String的concat方法 3.使用StringBuilder的append方法 4.使用StringBuffer的append方法 由于String是final类型的,因此String对象都是属于不可变对象,因此,在需要对字符串进行修改操作的时候(比如字符串的连接或者是替换),String总是会生成新的对象. 1."+" 如果不考虑其他,使用"+"号来连接字符串无疑是最

  • Java中字符串拼接的一些细节分析

    工作日忙于项目的逻辑实现,周六有点时间,从书柜里拿出厚厚的英文版Thinking In Java,读到了字符串对象的拼接.参考着这本书做个翻译,加上自己思考的东西,写上这篇文章记录一下. 不可变的String对象 在Java中,String对象是不可变的(Immutable).在代码中,可以创建多个某一个String对象的别名.但是这些别名都是的引用是相同的. 比如s1和s2都是"droidyue.com"对象的别名,别名保存着到真实对象的引用.所以s1 = s2 复制代码 代码如下:

  • java 字符串的拼接的实现实例

    java 字符串的拼接的实现实例 在实际的开发工作中,对字符串的处理是最常见的编程任务.本题目即是要求程序对用户输入的串进行处理.具体规则如下: 1. 把每个单词的首字母变为大写. 2. 把数字与字母之间用下划线字符(_)分开,使得更清晰 3. 把单词中间有多个空格的调整为1个空格. 例如: 用户输入: you and     me what  cpp2005program 则程序输出: You And Me What Cpp_2005_program 用户输入: this is     a  

  • Java 8中字符串拼接新姿势StringJoiner详解

    在为什么阿里巴巴不建议在for循环中使用"+"进行字符串拼接一文中,我们介绍了几种Java中字符串拼接的方式,以及优缺点.其中还有一个重要的拼接方式我没有介绍,那就是Java 8中提供的StringJoiner ,本文就来介绍一下这个字符串拼接的新兵. 如果你想知道一共有多少种方法可以进行字符串拼接,教你一个简单的办法,在Intellij IDEA中,定义一个Java Bean,然后尝试使用快捷键自动生成一个toString方法,IDEA会提示多种toString生成策略可供选择. 1

  • Java字符拼接成字符串的注意点详解

    这两天敲代码的时候,偶然间发现一个好玩的事情,分享一下,记录一下. 该段代码主要是:先产生的几个整数,把整数转换成对应的字符,最后的字符拼接成字符串,在把字符拼接成字符串的时候,个人因为偷懒使用+号进行操作,出现了一点小惊喜.拼接以后出现了两种不同的结果,感到十分的意外,所以分析了一下出现的结果,记录一下. package top.supertd.www; import java.util.concurrent.ThreadLocalRandom; public class TestString

  • java拼接字符串时去掉最后一个多余逗号的方法

    本文实例讲述了java拼接字符串时去掉最后一个多余逗号的方法.分享给大家供大家参考.具体分析如下: 先看下面这段代码: for (int t = 0; t < memberLen; t++) { memTemp = stafferMap.get(strMember[t]); if(memTemp != null){ memberNames += memTemp + ","; } } 以上的代码,拼接的字符串会多一个",",比如:"str1,str2,

  • java中拼接字符串的5种方法效率对比

    前言 最近写一个东东,可能会考虑到字符串拼接,想了几种方法,但对性能未知,所以下面就来测试下面,话不多说了,来一起看看详细的介绍吧. 示例代码 public class Test { List<String> list = new ArrayList<>(); @Before public void init(){ IntStream.range(0, 100000).forEach((index) -> { list.add("str" + index)

随机推荐