咱们提出一个需求:有一个 List<String>
,将其格式化为 元素1, 元素2, 元素3, ... 元素N 的字符串形式。app
毋庸置疑,Java8 以前咱们的第一反应是使用 StringBuilder
:函数
public static String formatList(List<String> list, String delimiter) { StringBuilder result = new StringBuilder(); for (String str : list) { result.append(str).append(delimiter); } // 删除末尾多余的 delimiter result.delete(result.length() - delimiter.length(), result.length()); return result.toString(); } public static void main(String[] args) throws Exception { List<String> list = Arrays.asList("a", "b", "c", "d", "e", "f", "g"); System.out.println("使用 StringBuilder:"); String format = formatList(list, ", "); System.out.println(format); }
运行结果:ui
JDK1.8 时,添加了一个新的用于字符串链接的类,专门用于这种须要 分隔符 的场合,它就是 StringJoiner
。StringJoiner
在构造时能够指定一个分隔符(delimiter),而后每链接一个元素它便会加上一个 delimiter,使用 StringJoiner
改写 formatList
:编码
public static String formatList(List<String> list, String delimiter) { StringJoiner result = new StringJoiner(delimiter); for (String str : list) { result.add(str); } return result.toString(); } public static void main(String[] args) throws Exception { List<String> list = Arrays.asList("a", "b", "c", "d", "e", "f", "g"); System.out.println("使用 StringJoiner:"); String format = formatList(list, ", "); System.out.println(format); }
运行结果:spa
formatList
的代码更加的简洁了 —— 固然咱们还能够更简洁 —— JDK1.8 为 String
类添加了一个新的静态方法,String.join
:code
能够看到,第一个参数为一个分隔符 delimiter,第二个参数能够是一个 Iterable
,或者是一个变长参数的 CharSequence
(String
就是 CharSequence
的子类)。
因此 formatList
方法只须要一句代码就搞定:orm
public static String formatList(List<String> list, String delimiter) { return String.join(delimiter, list); }
固然,咱们能猜到,String.join
方法的功能内部是经过 StringJoiner
来实现的,String.join (CharSequence, Iterable)
的源码:blog
可是咱们看到了 String.join
方法的不足 —— 它不能指定前缀和后缀 —— 好比咱们若是想要直接将 List<String>
格式化为 { 元素1, 元素2, 元素3, ... 元素N } 呢?(此时前缀为 "{ "
,后缀为 " }"
)字符串
查看 StringJoiner
的构造方法,发现 StringJoiner
除了指定 分隔符 的构造方法,还有一个能够指定 分隔符、前缀和后缀 的构造方法:源码
修改 formatList
:
public static String formatList( List<String> list, String delimiter, String prefix, String suffix) { StringJoiner result = new StringJoiner(delimiter, prefix, suffix); for (String str : list) { result.add(str); } return result.toString(); } public static void main(String[] args) throws Exception { List<String> list = Arrays.asList("a", "b", "c", "d", "e", "f", "g"); System.out.println("使用 StringJoiner,带前缀和后缀:"); String format = formatList(list, ", ", "{ ", " }"); System.out.println(format); }
运行结果:
很棒~ 但能不能更简洁呢? 事实上,Java8 对于字符串集合的链接操做提供了一个专门的流式 API,即 Collectors.joining
函数:
joining()
方法,即不存在链接符(底层实现为 StringBuilder
);joining(CharSequence delimiter)
方法,即分隔符为 delimiter(底层实现为 StringJoiner
);joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix)
方法,即分隔符为 delimiter,前缀为 prefix,后缀为 suffix(底层实现为 StringJoiner
)。那怎么使用呢? 咱们直接使用三个参数的 Collectors.joining
方法改写 formatList
:
public static String formatList( List<String> list, String delimiter, String prefix, String suffix) { return list.stream().collect(Collectors.joining(delimiter, prefix, suffix)); } public static void main(String[] args) throws Exception { List<String> list = Arrays.asList("a", "b", "c", "d", "e", "f", "g"); System.out.println("使用 Collectors.joining:"); String format = formatList(list, ", ", "{ ", " }"); System.out.println(format); }
运行结果:
查看 StringJoiner
的源码,咱们能够知道 StringJoiner
的底层实现就是 StringBuilder
—— Java8 将 使用分隔符链接多个字符串 这一功能进行封装,提供这么多易用且简介的 API,确实在很大程度上方便了编码。