浅谈Java8对字符串连接的改进正确姿势

我们提出一个需求:有一个 List<String>,将其格式化为 元素1, 元素2, 元素3, ... 元素N 的字符串形式。

毋庸置疑, 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);
}

运行结果:

JDK1.8 时,添加了一个新的用于字符串连接的类,专门用于这种需要 分隔符 的场合,它就是 StringJoinerStringJoiner 在构造时可以指定一个分隔符(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);
}

运行结果:

formatList 的代码更加的简洁了 —— 当然我们还可以更简洁 —— JDK1.8 为 String 类添加了一个新的静态方法, String.join

可以看到,第一个参数为一个分隔符 delimiter ,第二个参数可以是一个 Iterable ,或者是一个变长参数的 CharSequenceString 就是 CharSequence 的子类)。 所以 formatList 方法只需要一句代码就搞定:

public static String formatList(List<String> list, String delimiter) {
 return String.join(delimiter, list);
}

当然,我们能猜到, String.join 方法的功能内部是通过 StringJoiner 来实现的, String.join (CharSequence, Iterable) 的源码:

但是我们看到了 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);j

oining(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,确实在很大程度上方便了编码。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Java8新特性之字符串去重介绍

    8月19日,Oracle发布了JDK 8u20,JDK 8u20包含很多新特性,比如Java编译器更新.支持在运行时通过API来修改MinHeapFreeRatio和MaxHeapFreeRatio参数.新的GC调优指南文档.不过在众多新特性中,最令人期待的还属字符串去重(String Deduplication ).如何减少内存占用一直是一个永恒的话题,而在Java应用中,经常会看到String对象会占用应用30%的内存,它是Java中最常用的对象之一.新的字符串去重特性可以帮助减少应用中St

  • Java8中字符串处理库strman-java的使用示例

    介绍 Strmen-java是一个字符串处理工具,你可以通过maven将它引入到项目中.Strmen-java为我们提供了一个非常完整且强大的解决方案,使用它可以解决几乎所有字符串处理场景. 使用 为了能在你的Java应用程序中使用strman-java,可以把这个包下载下来添加到你项目的lib目录中,如果使用的是Maven做项目管理,则只需要在你的pom.xml中加入如下依赖即可: <dependency> <groupId>com.shekhargulati</group

  • java8、jdk8日期转化成字符串详解

    java8.jdk8日期转化成字符串 新建日期工具类:DateUtils 新建方法:parseDate 实现方法parseDate public static String parseDate(LocalDate localDate,String pattern) { DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern); return localDate.format(dateTimeFormatt

  • java8 统计字符串字母个数的几种方法总结(推荐)

    1.统计字符串字母个数(并且保持字母顺序) 比如: aabbbbbbbba喔喔bcab cdabc deaaa 目前我做知道的有5种方式噢,如果你还有更好的,欢迎赐教 //方式1 public static void letterCount1(String s) { s=s.replaceAll(" +", ""); //1,转换成字符数组 char c[]=s.toCharArray(); Map<Character, Integer> tree=ne

  • 浅谈Java8对字符串连接的改进正确姿势

    我们提出一个需求:有一个 List<String>,将其格式化为 元素1, 元素2, 元素3, ... 元素N 的字符串形式. 毋庸置疑, Java8 之前我们的第一反应是使用 StringBuilder : public static String formatList(List<String> list, String delimiter) { StringBuilder result = new StringBuilder(); for (String str : list)

  • 浅谈Python xlwings 读取Excel文件的正确姿势

    使用Python加载最新的Excel读取类库xlwings可以说是Excel数据处理的利器,但使用起来还是有一些注意事项,否则高大上的Python会跑的比老旧的VBA还要慢. 这里我们对比一下,用几种不同的方法,从一个Excel表格中读取一万行数据,然后计算结果,看看他们的耗时. 1. 处理要求: 一个Excel表格中包含了3万条记录,其中B,C两个列记录了某些计算值,读取前一万行记录,将这两个列的差值进行计算,然后汇总得出差的和. 文件是这个样子:Book300s.xlsx . 2. 处理方式

  • 浅谈Express.js解析Post数据类型的正确姿势

    一.概念介绍 1.POST请求:HTTP/1.1 协议规定的 HTTP 请求方法有 OPTIONS.GET.HEAD.POST.PUT.DELETE.TRACE.CONNECT 这几种.其中 POST 一般用来向服务端提交数据. 2. Content-Type : 是指 http/https 发送信息至服务器时的内容编码类型, Content-Type 用于表明发送数据流的类型,服务器根据编码类型使用特定的解析方式,获取数据流中的数据.四种常见的 POST 请求的 Content-Type 数据

  • 浅谈使用 Yii2 AssetBundle 中 $publishOptions 的正确姿势

    本文介绍了使用 Yii2 AssetBundle 中 $publishOptions 的正确姿势,分享给大家,具体如下: 官方文档:http://www.yiiframework.com/doc-2.0/guide-structure-assets.html 有兴趣的同学可以先看下官方原文档 文档样例代码 <?php namespace app\assets; use yii\web\AssetBundle; class FontAwesomeAsset extends AssetBundle

  • 浅谈java8 stream flatMap流的扁平化操作

    概念: Steam 是Java8 提出的一个新概念,不是输入输出的 Stream 流,而是一种用函数式编程方式在集合类上进行复杂操作的工具.简而言之,是以内部迭代的方式处理集合数据的操作,内部迭代可以将更多的控制权交给集合类.Stream 和 Iterator 的功能类似,只是 Iterator 是以外部迭代的形式处理集合数据的操作. 在Java8以前,对集合的操作需要写出处理的过程,如在集合中筛选出满足条件的数据,需要一 一遍历集合中的每个元素,再把每个元素逐一判断是否满足条件,最后将满足条件

  • 浅谈jquery拼接字符串效率比较高的方法

    实例如下: var roleidArray = new Array(""); for(i = 0; i < rightRows.length; i++) { roleidArray.push(rightRows[i].id); } roleidArray = roleidArray.join(",").substring(1); 代码很简单,我就不做注释了 以上这篇浅谈jquery拼接字符串效率比较高的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,

  • 浅谈java8中map的新方法--replace

    Map在Java8中新增了两个replace的方法 1.replace(k,v) 在指定的键已经存在并且有与之相关的映射值时才会将指定的键映射到指定的值(新值) 在指定的键不存在时,方法会return回来一个null javadoc的注释解释了该默认值方法的实现的等价Java代码: if (map.containsKey(key)) { return map.put(key, value); } else { return null; } 下面展示的是新方法和JDK8之前的方法比较: /* *

  • 浅谈java中字符串数组、字符串、整形之间的转换

    字符串数组转字符串(只能通过for循环): String[] str = {"abc", "bcd", "def"}; StringBuffer sB = new StringBuffer(); for (int i = 0; i < str.length;i++) { sB.append(str[i]); } String s = sB.toString(); 字符数组转字符串可以通过下面的方式: char[] data = {"

  • 浅谈Mysql多表连接查询的执行细节

    先构建本篇博客的案列演示表: create table a(a1 int primary key, a2 int ,index(a2)); --双字段都有索引 create table c(c1 int primary key, c2 int ,index(c2), c3 int); --双字段都有索引 create table b(b1 int primary key, b2 int); --有主键索引 create table d(d1 int, d2 int); --没有索引 insert

  • 浅谈Java8新特性Predicate接口

    一.前言 Java 8中引入了Predicate功能接口. Java Predicate表示一个参数的谓词. Predicate是一个布尔值的函数. Java Predicate是一个功能接口,属于java.util.function包. Predicate的功能方法是test(T t). Predicate的其他方法是test.isEqual.and.or.negate和not. not方法在Java 11中被引入. 在本文章,我们将提供Predicate的例子及其所有方法. 二.test(T

随机推荐