字符串拼接还在用StringBuilder?快试试Java8中的StringJoiner吧,真香!

开发 后端
我们经常会通过StringBuffer或者StingBuilder对字符串进行拼接,但是你知道Java8中推出的StringJoiner吗?它比前者更加优美、灵活,如果你现在还使用StringBuffer拼接,强烈推荐你试试StringJoiner。

[[394661]]

 前言

之前,我们经常会通过StringBuffer或者StingBuilder对字符串进行拼接,但是你知道Java8中推出的StringJoiner吗?它比前者更加优美、灵活,如果你现在还使用StringBuffer拼接,强烈推荐你试试StringJoiner。

介绍

在实用StringJoiner类之前,如果我们想要数据最终的字符串以逗号隔开,大概是这样的 

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

如果引入StringJoiner,如何处理呢? 

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

看着是不是更简单直观了呢?

另外,StringJoiner类的构造函数,还可以做到可选择性地从我们自定义的前缀开始和自定义的后缀结尾,比较灵活和实用。 

  1. //值依次是分割符 , 前缀  ,后缀  
  2. StringJoiner stringJoiner = new StringJoiner(",", "[", "]");  
  3.         stringJoiner.add("xiao");  
  4.         stringJoiner.add("zhi");  
  5.         System.out.println(stringJoiner.toString());   

输出结果:[xiao,zhi]

StringJoiner在处理sql拼接上面,也非常方便,如拼接 sql 的in条件的时候: 

  1. StringJoiner joiner3 = new StringJoiner("','", "'", "'");  
  2. joiner3.add("1").add("2");  
  3. //输出 : '1','2' 

更多实用的功能,大家可以探索。

源码

这个类的源码很简单,大家很容易就可以看明白。StringJoiner 更像一个装饰者模式,对外隐藏了StringBuilder。

不过需要注意的是 StringJoiner 并且没有处理一些基本的集合元素情况,比如加入列表的元素,更像针对Collectors而设计。 

  1. package java.util;  
  2. public final class StringJoiner {  
  3.     private final String prefix;//前缀  
  4.     private final String delimiter;//间隔符  
  5.     private final String suffix;//后缀  
  6.     private StringBuilder value;//值  
  7.     private String emptyValue;//空值  
  8.     public StringJoiner(CharSequence delimiter) {  
  9.         this(delimiter, "", "");  
  10.         //默认前缀和后缀为"",重载调用  
  11.     }  
  12.     public StringJoiner(CharSequence delimiter,  
  13.                         CharSequence prefix,  
  14.                         CharSequence suffix) {  
  15.         //间隔符,前缀和后缀判断是否为null,null将抛出异常  
  16.         Objects.requireNonNull(prefix, "The prefix must not be null");  
  17.         Objects.requireNonNull(delimiter, "The delimiter must not be null"); 
  18.         Objects.requireNonNull(suffix, "The suffix must not be null");   
  19.         // 成员变量赋值  
  20.         this.prefix = prefix.toString();  
  21.         this.delimiter = delimiter.toString();  
  22.         this.suffix = suffix.toString();  
  23.         thisthis.emptyValue = this.prefix + this.suffix;//空值被设置为只有前后缀  
  24.     }  
  25.  //设置空值,检查是否为null  
  26.     public StringJoiner setEmptyValue(CharSequence emptyValue) {  
  27.         this.emptyValue = Objects.requireNonNull(emptyValue,  
  28.             "The empty value must not be null").toString();  
  29.         return this;  
  30.     }  
  31.     @Override  
  32.     public String toString() {  
  33.         if (value == null) {  
  34.             return emptyValue;  
  35.             //没有值将返回空值或者后续设置的空值  
  36.         } else {  
  37.             if (suffix.equals("")) {  
  38.                 return value.toString();  
  39.                 //后缀为""直接返回字符串,不用添加  
  40.             } else {  
  41.              //后缀不为"",添加后缀,然后直接返回字符串,修改长度  
  42.                 int initialLength = value.length();  
  43.                 String result = value.append(suffix).toString();  
  44.                 // reset value to pre-append initialLength  
  45.                 value.setLength(initialLength);  
  46.                 return result;  
  47.             }  
  48.         }  
  49.     }  
  50.     //初始化,先添加前缀,有了之后每次先添加间隔符,StringBuilder后续append字符串  
  51.     public StringJoiner add(CharSequence newElement) {  
  52.         prepareBuilder().append(newElement);  
  53.         return this;  
  54.     }  
  55.  //合并StringJoiner,注意后面StringJoiner 的前缀就不要了,后面的appen进来  
  56.     public StringJoiner merge(StringJoiner other) {  
  57.         Objects.requireNonNull(other);  
  58.         if (other.value != null) {  
  59.             final int length = other.value.length();  
  60.             // lock the length so that we can seize the data to be appended  
  61.             // before initiate copying to avoid interference, especially when  
  62.             // merge 'this'  
  63.             StringBuilder builder = prepareBuilder();  
  64.             builder.append(other.value, other.prefix.length(), length);  
  65.         }  
  66.         return this;  
  67.     }  
  68.  //初始化,先添加前缀,添加之后每次先添加间隔符  
  69.     private StringBuilder prepareBuilder() {  
  70.         if (value != null) {  
  71.             value.append(delimiter);  
  72.         } else {  
  73.             value = new StringBuilder().append(prefix);  
  74.         } 
  75.         return value;  
  76.     }  
  77.     public int length() {  
  78.         // Remember that we never actually append the suffix unless we return 
  79.         // the full (present) value or some sub-string or length of it, so that  
  80.         // we can add on more if we need to. 
  81.         //添加后缀的长度  
  82.         return (value != null ? value.length() + suffix.length() :  
  83.                 emptyValue.length());  
  84.     }  
  85.  

 

责任编辑:庞桂玉 来源: Java编程
相关推荐

2019-02-27 09:08:20

Java 8StringJoineIDEA

2021-08-13 12:53:42

StringBuildStringJoineJava

2017-01-19 11:26:55

Java 8StringBuild

2016-12-27 09:46:55

Java 8StringBuild

2010-06-24 09:38:42

Windows备份云平台

2011-07-11 16:00:22

字符串拼接

2013-06-24 15:16:29

Java字符串拼接

2019-09-21 21:32:34

数据库SQL分布式

2024-01-23 13:20:00

分库分表分布式

2024-03-18 00:00:00

CalendaJava8Date

2022-11-25 07:53:26

bash脚本字符串

2020-11-19 07:51:06

StringJoine分隔符使用

2021-06-11 18:08:00

Java字符串拼接

2024-03-11 08:21:49

2023-10-31 18:57:02

Java字符串

2023-02-01 10:40:01

2021-05-31 07:57:00

拼接字符串Java

2021-12-06 17:44:56

MHAMySQL高可用

2011-07-11 15:36:44

JavaScript

2016-10-12 10:18:53

Java字符串源码分析
点赞
收藏

51CTO技术栈公众号