如何将Java Streams处理后的字符串收集到已有的StringBuilder中?
解决方案
当然可以直接把流处理后的内容追加到已有的StringBuilder里,这里提供两种实用的方式:
方式一:先过滤再循环处理分隔符
这种方法直观易懂,先过滤掉空路径,再通过循环控制分隔符的添加,避免出现多余的斜杠:
public String build() { StringBuilder s3Key = new StringBuilder(); if (bucketName == null || fileName == null) { throw new IllegalStateException("Bucket name and file name are required"); } s3Key.append(bucketName); // 过滤非空路径 List<String> nonEmptyPaths = paths.stream() .filter(Predicate.not(Strings::isNullOrEmpty)) .toList(); // 逐个追加到StringBuilder,处理分隔符 for (int i = 0; i < nonEmptyPaths.size(); i++) { if (i > 0) { s3Key.append("/"); } s3Key.append(nonEmptyPaths.get(i)); } s3Key.append(fileName); return s3Key.toString(); }
方式二:自定义Collector直接收集到已有StringBuilder
如果想完全用流的风格实现,可以自定义一个Collector,直接把过滤后的路径元素用分隔符拼接并追加到已有的StringBuilder中:
public String build() { StringBuilder s3Key = new StringBuilder(); if (bucketName == null || fileName == null) { throw new IllegalStateException("Bucket name and file name are required"); } s3Key.append(bucketName); paths.stream() .filter(Predicate.not(Strings::isNullOrEmpty)) .collect(Collector.of( // 供应器:使用已有的StringBuilder () -> s3Key, // 累加器:处理分隔符并追加路径 (sb, path) -> { // 仅当已有内容(已追加bucketName)且不是第一个路径时添加分隔符 if (sb.length() > bucketName.length()) { sb.append("/"); } sb.append(path); }, // 合并器:并行流场景下合并两个StringBuilder (sb1, sb2) -> sb1.append(sb2) )); s3Key.append(fileName); return s3Key.toString(); }
注意事项
- 两种方式都避免了额外创建中间字符串对象,相比原来先
collect成字符串再append的方式,内存使用更高效,尤其是路径数量较多时。 - 如果你的路径列表不会太大,方式一的可读性更好,推荐优先使用;方式二更适合追求纯流编程风格的场景。
内容的提问来源于stack exchange,提问作者Jordi
相关产品推荐
相关产品推荐

