当前位置: 首页 > 科技观察

Java8字符串拼接新姿势:StringJoiner

时间:2023-03-21 00:18:25 科技观察

在为什么阿里巴巴不推荐在for循环中使用“+”进行字符串拼接一文中,我们介绍了Java中字符串拼接的几种方式,以及它们的优势和优势缺点。还有一个重要的拼接方法我没有介绍,那就是Java8中提供的StringJoiner,本文将介绍这个用于字符串拼接的新招。如果你想知道拼接字符串有多少种方法,我教你一个简单的方法。在IntellijIDEA中,定义一个JavaBean,然后尝试使用快捷键自动生成一个toString方法。IDEA会提示你生成多个toString。策略可用。目前我使用的IDEA的toString生成策略默认使用JDK1.8提供的StringJoiner。1.简介StringJoiner是java.util包中的一个类,用于构造由定界符(可选)分隔的字符序列,可以从提供的前缀开始,以提供的后缀结束。虽然这也可以在StringBuilder类的帮助下在每个字符串后附加一个分隔符,但StringJoiner提供了无需编写大量代码即可完成此操作的简单方法。StringJoiner类有2个构造函数和5个公共方法。最常用的方法是add方法和toString方法,类似于StringBuilder中的append方法和toString方法。2.用法StringJoiner的用法比较简单。在下面的代码中,我们使用StringJoiner进行字符串拼接。publicclassStringJoinerTest{publicstaticvoidmain(String[]args){StringJoinersj=newStringJoiner("Hollis");sj.add("hollishuang");sj.add("Java干货");System.out.println(sj.toString());StringJoinersj1=newStringJoiner(":","[","]");sj1.add("霍利斯").add("霍利斯爽").add("Java干货");System.out.println(sj1.toString());}}上面代码输出结果:hollishuangHollisJava干货[Hollis:hollishuang:Java干货]值得注意的是,当我们使用StringJoiner(CharSequencedelimiter)初始化一个StringJoiner时,分隔符实际上是一个分隔符,不是可变字符串的初始值。StringJoiner(CharSequencedelimiter,CharSequenceprefix,CharSequencesuffix)的第二个和第三个参数分别是拼接字符串的前缀和后缀。3.原理介绍完简单的用法,我们再来看看这个StringJoiner的原理,看看它是如何实现的。主要看add方法:publicStringJoineradd(CharSequencenewElement){prepareBuilder().append(newElement);returnthis;}privateStringBuilderprepareBuilder(){if(value!=null){value.append(delimiter);}else{value=newStringBuilder().append(prefix);}returnvalue;}看到了一个熟悉的身影——StringBuilder,没错,StringJoiner其实就是依赖StringBuilder实现的,为什么阿里巴巴不推荐在for循环中使用“+”进行字符串拼接,我们已经介绍过了StringBuilder的实现原理,本文不再赘述。当我们发现StringJoiner实际上是由StringBuilder实现的时候,我们大概可以猜到StringJoiner的性能损失应该和直接使用StringBuilder差不多吧!为什么需要StringJoiner在了解了StringJoiner的用法和原理之后,很多读者可能会有一个疑问,明明已经有了StringBuilder,为什么Java8还要定义一个StringJoiner呢?有什么好处?如果读者对Java8足够了解,或许可以猜到它一定与Stream有关。作者还在Java文档中找到了答案:AStringJoinermaybeemployedtocreateformattedoutputfromaStreamusingCollectors.joining(CharSequence)想象一下,在Java中,如果我们有这样一个列表:Listlist=ImmutableList.of("Hollis","hollishuang","Java干货");如果我们想将其拼接成如下形式的字符串:hollis,hollishuang,Java干货可以通过以下方式完成:StringBuilderbuilder=newStringBuilder();if(!list.isEmpty()){builder.append(list.get(0));for(inti=1,n=list.size();isb.append(s).append(','),StringBuilder::append).toString();但是输出结果略有不同,需要二次处理:hollis,hollishuang,Java干货,也可以用“+”进行拼接:list.stream().reduce((a,b)->a+”,"+b).toString();上述方法要么代码复杂,性能低下,要么不能直接得到想要的结果。为了满足这样的需求,Java8中提供的StringJoiner就派上用场了。以上需求只需要一行代码:list.stream().collect(Collectors.joining(":"))。上面使用的表达式中,Collector.joining的源码如下:,StringJoiner::add,StringJoiner::merge,StringJoiner::toString,CH_NOID);}Collector.joining的实现原理是使用StringJoiner。当然,或许在Collector中直接使用StringBuilder似乎也能实现类似的功能,只是麻烦了一点。因此在Java8中提供了StringJoiner来丰富Stream的使用。此外,StringJoiner还可以方便地添加前缀和后缀。比如我们要获取的字符串是“[Hollis,hollishuang,Java干货]”而不是“Hollis,hollishuang,Java干货”,StringJoiner的优势就更加明显了。4.小结本文介绍Java8中提供的可变字符串类——StringJoiner,可用于字符串拼接。StringJoiner实际上是通过StringBuilder实现的,所以它的性能和StringBuilder差不多,也是非线程安全的。如果在日常开发中需要进行字符串拼接,应该如何选择呢?1、如果只是简单的字符串拼接,可以考虑直接使用“+”。2.如果在for循环中进行字符串拼接,可以考虑使用StringBuilder和StringBuffer。3、如果通过集合(比如List)进行字符串拼接,可以考虑使用StringJoiner。4.如果是拼接一组数据,可以考虑转成Stream,使用StringJoiner处理。【本文为专栏作家霍利斯原创文章,作者微信公众号Hollis(ID:hollishuang)】点此阅读更多本作者好文