上一篇:字节实习生开发的 AI 竟然被网友用在了王冰冰身上!

在阅读项目代码是,突然看到了StringJoiner这个类的使用,感觉很有意思,对实际开发中也有用,实际上是运用了StringBuilder的一个拼接字符串的封装处理。

为什么会新增这样一个String辅助类?

原有的StringBuilder太死板,不支持分割,如果想让最终的字符串以逗号隔开,需要这样写

StringBuilder sb = new StringBuilder();
IntStream.range(1,10).forEach(i->{sb.append(i+"");if( i < 10){sb.append(",")}
});

是不是太死板了,不好用,StringJoiner怎样写呢?

StringJoiner sj = new StringJoiner(",");
IntStream.range(1,10).forEach(i->sj.add(i+""));

有哪些平时用的还比较少的功能:

  • setEmptyValue, 默认情况下的emptyValue是前缀加后缀, 用户可自定义emptyValue

  • merge(StringJoiner other),合并另外一个joiner

  • length, 当前长度,为空看emptyValue的长度

让我实现StringJoiner,我会怎么办呢?

维护一个List,最后toString的时候join一下就好了
优势:实现非常方便
缺点:list太浪费空间(扩容时都是按照系数扩容的)
在StringBuilder基础上改造(jdk实现方式就是以组合的形式增强的StringBuilder)

jdk实现的源码分析

成员变量

private final String prefix;private final String delimiter;private final String suffix;/** StringBuilder value -- at any time, the characters constructed from the* prefix, the added element separated by the delimiter, but without the* suffix, so that we can more easily add elements without having to jigger* the suffix each time.*/private StringBuilder value;/** By default, the string consisting of prefix+suffix, returned by* toString(), or properties of value, when no elements have yet been added,* i.e. when it is empty.  This may be overridden by the user to be some* other value including the empty String.*/private String emptyValue;

其实从成员变量的注释里就能看出他们的作用和需要注意的点了

构造函数

public StringJoiner(CharSequence delimiter,CharSequence prefix,CharSequence suffix) {Objects.requireNonNull(prefix, "The prefix must not be null");Objects.requireNonNull(delimiter, "The delimiter must not be null");Objects.requireNonNull(suffix, "The suffix must not be null");// make defensive copies of argumentsthis.prefix = prefix.toString();this.delimiter = delimiter.toString();this.suffix = suffix.toString();// !!!构造时就直接将emptyValue拼接好了。this.emptyValue = this.prefix + this.suffix;}

为什么要一开始就构造好呢?如果我想直接自定义emptyValue直接用构造函数初始化不是更方便吗?是因为绝大多数场景下都不会自定义emptyValue的场景吗?不对啊,感觉这个场景非常必要啊。。。

添加元素

public StringJoiner add(CharSequence newElement) {prepareBuilder().append(newElement);return this;
}private StringBuilder prepareBuilder() {// 从构造函数和类变量的声明可以看出,没有添加元素前stringbuilder是没有初始化的if (value != null) {// 已经有元素存在的情况下,添加元素前先将分隔符添加进去value.append(delimiter);} else {// 没有元素存在的情况下先把前缀加进去value = new StringBuilder().append(prefix);}return value;
}

可以看出再添加元素的过程中就已经把前缀和分割字符什么的都处理好了,全部都在stringbuilde中了,唯一没有处理的就是后缀。为什么?这样做tostring什么的时候真的超级方便的有木有。。。。。

关键的toString

public String toString() {if (value == null) {// 这里如果没有自定义空值就是前缀+后缀咯。。return emptyValue;} else {// 为什么不直接value.toString()+suffix?????if (suffix.equals("")) {return value.toString();} else {int initialLength = value.length();String result = value.append(suffix).toString();// reset value to pre-append initialLengthvalue.setLength(initialLength);return result;}}}

为什么不直接value.toString()+suffix?答案在merge方法

merge

public StringJoiner merge(StringJoiner other) {Objects.requireNonNull(other);if (other.value != null) {final int length = other.value.length();// 下面这段注释是说避免merge(this)时受影响,为什么?// lock the length so that we can seize the data to be appended// before initiate copying to avoid interference, especially when// merge 'this'StringBuilder builder = prepareBuilder();builder.append(other.value, other.prefix.length(), length);}return this;}private StringBuilder prepareBuilder() {if (value != null) {value.append(delimiter);} else {value = new StringBuilder().append(prefix);}return value;}

merge的思路是用当前的striingBuilder去append other的value(必须去掉前缀),源码注释中的merge 'this'问题是什么呢?prepareBuilder()的时候可能会先append(delimiter),如果other就是this,那么length其实就多了一个delimiter,此时append还是得以添加前的length为准。

merge的实现方式决定了toString时不能直接value.append(suffix).toString(),因为
builder.append(other.value, other.prefix.length(), length);这行代码,默认加上suffix后这里的merge的length得减去suffix的length(嗯,看来作者是想得多好多),而且merge时得把另外一个sj的内容append到当前这个sj的suffix之前(想想就麻烦多了。。。。)

length

public int length() {// Remember that we never actually append the suffix unless we return// the full (present) value or some sub-string or length of it, so that// we can add on more if we need to.return (value != null ? value.length() + suffix.length() :emptyValue.length());}

没什么好说的,记住length不只是add的元素的length,还有前后缀。

总结

基于StringBuilder实现,add时就把prefix和分隔符给加上了,suffix永远都不加,知道toString和length调用时才加入计算。这样带来的merge操作实现的极大便利性!!!!!学到了,真的不错

emptyValue这个一定要构造时就生成吗?用户想有自己的默认值还需要先构造实例再注入吗。。。。这个觉得还是有点奇怪

Objects这个工具方法是返回的校验的值本身,不错。

public StringJoiner setEmptyValue(CharSequence emptyValue) {
// 注意这个Objects.requireNonNull方法是return的第一个参数。。。this.emptyValue = Objects.requireNonNull(emptyValue,"The empty value must not be null").toString();return this;
}

感谢您的阅读,也欢迎您发表关于这篇文章的任何建议,关注我,技术不迷茫!小编到你上高速。

· END ·

最后,关注公众号互联网架构师,在后台回复:2T,可以获取我整理的 Java 系列面试题和答案,非常齐全。

正文结束

推荐阅读 ↓↓↓

1.不认命,从10年流水线工人,到谷歌上班的程序媛,一位湖南妹子的励志故事

2.如何才能成为优秀的架构师?

3.从零开始搭建创业公司后台技术栈

4.程序员一般可以从什么平台接私活?

5.37岁程序员被裁,120天没找到工作,无奈去小公司,结果懵了...

6.IntelliJ IDEA 2019.3 首个最新访问版本发布,新特性抢先看

7.这封“领导痛批95后下属”的邮件,句句扎心!

8.15张图看懂瞎忙和高效的区别!

一个人学习、工作很迷茫?

点击「阅读原文」加入我们的小圈子!

不用StringBuilder!Java8的StringJoiner,也很香!相关推荐

  1. 你只会用 StringBuilder?试试 StringJoiner,真香!

    你只会用 StringBuilder/ StringBuffer 拼接字符串? 那你就 OUT 了!! 如果需要拼接分隔符的字符串,建议使用 Java 8 中的这款拼接神器:StringJoiner, ...

  2. Windows 的这款工具,有时让我觉得 Mac 不是很香

    你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand it well enough ...

  3. 电子垃圾也很香 篇一:垃圾佬捡个路由器1:选择与刷机

    电子垃圾也很香 篇一:垃圾佬捡个路由器1:选择与刷机 前言 最近丈母娘总是抱怨家里的路由器不好用,总是动不动就断网.丈母娘的需求必须得满足啊,目前丈母娘家用的是tp的wr740n垃圾路由器,立马着手准 ...

  4. 运营电商平台系统,功能强大真的很香!

    消费者进入到电商系统后,浏览商品到下单结算等一系列的操作都离不开系统功能的支持,从电商平台的管理.运营.推广.营销.转化来看,功能模块作为基础支持,运营者始终认为策略才是核心,但是电商平台系统的功能强 ...

  5. 截取小数点_五年级上册系列| 小数点位置变化名师微课+课本+学案,暑假预科,很香!...

    点击蓝字关注我们 李艳玲工作室微课展播[总142期] 主讲教师:徐素平 电子课本 学 案 小数乘法 [学习目标] 1.熟练掌握小数点的移动引起小数大小变化的规律,并能举一反三,灵活运用. 2.自主探索 ...

  6. 微服务很香--麻辣味,但要慢慢消化

    前言 微服务在编程圈火的是不行不行的啦,可能还有很多小伙伴还没有进行微服务实操,但这个词,要说没听过.没看过,那小伙伴一定是假Programmer. 虽然微服务很火,但不能盲目使用:先不说涉及技术和工 ...

  7. java stringjoiner_java-为什么我们已经拥有StringBuilder时使用StringJoiner?

    java-为什么我们已经拥有StringBuilder时使用StringJoiner? 我最近遇到了Java 8类StringBuilder,该类使用定界符添加String并向其添加前缀和后缀,但是我 ...

  8. 洛克人html5,《洛克人Zero/Zx合集》:跳票冷饭,与预期有差但依旧很香

    前言 洛克人系列,卡普空旗下经典IP之一,一直都是以高难度著称,相信很多90后玩家的童年都有游玩洛克人的经历.从18年发布的洛克人11,整个系列发展有30余年,洛克人元组系列.X系列的合集早已上线St ...

  9. 某程序员感慨:996虽然辛苦,但发钱时真的很香,网友:真香定律

    996是近日被热议的话题,有人反对996,有人认为996是必经阶段,还有的人认为只要钱给够了,996不在话下,根本不是问题.一名阿里员工就吐露了自己的心声,在论坛上感慨了一番自己的经历,称996虽然痛 ...

  10. 苹果6能解掉id锁吗_起底闲鱼上的苹果游戏机,400块的苹果8很香,但并不建议购买...

    一直以来,苹果手机的A系列芯片的性能一直是傲视群雄的,但是苹果手机高昂的售价使得许多手头比较紧的高性能玩家望而却步.但是最近闲鱼上很火的廉价苹果游戏机满足了许多玩家对于高性能手机的需求,搭载强劲A11 ...

最新文章

  1. android timer弹出窗口,android – 如何在服务类中的Timer内显示AlertDialog?
  2. php企业网站源码安装教程,PHPSCUP企业建站系统v1.4 安装图文教程
  3. S3C6410的Bootloader的两个阶段BL1和BL2编译相关学习
  4. CodeForce 237C Primes on Interval(二分+ 素数筛法)
  5. JDEManual2 Overview
  6. CTFHub-Web-信息泄露
  7. 关于ElasticSearch性能调优几件必须知道的事
  8. 【自动驾驶-Autonomous】自动驾驶定义
  9. 进入hbase命令_Zookeeper、Hbase安装部署
  10. ASP.NET Core介绍
  11. 理解基本包装类型Number,String,Boolean
  12. JavaSE08:详解多线程(超详细)
  13. swf到html5转换器,iPixSoft SWF to HTML5 Converter(SWF到HTML5转换器) V3.6.0 官方版[安全工具]...
  14. 真格量化的回测交易撮合机制简介
  15. 5G相关协议下载路径
  16. [python爬虫]爬取英雄联盟所有英雄数据并下载所有英雄皮肤
  17. 【新番尝鲜】秀逗魔导士E-revolution——罪名:莉娜*因巴斯
  18. 搜狗多账户cookies最新接口可用推送工具免费使用【2020】
  19. 现在机器翻译效果已经那么牛逼了!?
  20. 电源接反了烧电路怎么办?电源防反接技术讨论

热门文章

  1. Mac 升级到 10.15 cocoapods使用不了
  2. 如何用iMazing来管理ios设备音频文件
  3. 企业数据安全防护不可忽视,数据丢失/损坏如何处理?
  4. Centos7.2下安装redis通用键值命令
  5. 一道有关switch-case题目
  6. TCP/UDP,SOCKET,HTTP,FTP 简析
  7. wojilu系统的ORM代码解析-[源代码结构分析,用特性和反射来感知属性-特性介绍篇]...
  8. 459B Pashmak and Flowers
  9. 如何在 macOS 中将用户帐户拆分为两个单独的帐户?
  10. 矢量绘图软件Sketch 82 for mac