如何在java 1.8的reduce方法中使用StringBuilder?

问题描述

String s = "apples for you";
StringBuilder returnString = new StringBuilder("");
Arrays.stream(s.split(" "))
        .reduce(returnString,(acc,str) -> acc.append(str.charat(0)));

期望输出每个单词的第一个字母,即afy

但在 acc.append 处出错,acc 被视为 String

解决方法

您对 reduce 的使用不正确。您打算调用的重载是具有 3 个参数的重载,它也应该对 StringBuilder 使用二元运算符:

StringBuilder returnString = Arrays.stream(s.split(" "))
        .reduce(new StringBuilder(""),(acc,str) -> acc.append(str.charAt(0)),(sb1,sb2) -> sb1.append(sb2));

如果您要在并行流上使用它,请执行可变归约(使用 stream.collect),否则可能会从多个线程不可预测地附加到初始标识字符串构建器对象:

StringBuilder returnString = Arrays.stream(s.split(" "))
        .collect(StringBuilder::new,StringBuilder::append);
,

ernest_k's answer 当然是正确的。不过,值得补充的是,您似乎正在使用 reduce 自己实现 joining 收集器,并且可能想直接使用它:

String result = 
  Arrays.stream(s.split(" ")).map(x -> x.substring(0,1)).collect(Collectors.joining());
,

您可以将 reduce 方法与 String 一起使用,而不是 StringBuilder

String str1 = "apples for you";
String str2 = Arrays
        // split string into an array of words
        .stream(str1.split("\\s+"))
        // first character of a word
        .map(str -> str.charAt(0))
        // character as string
        .map(String::valueOf)
        // reduce stream of strings to a single
        // string by concatenating them
        .reduce((s1,s2) -> s1 + s2)
        // otherwise null
        .orElse(null);

System.out.println(str2); // afy

另见:Using Streams instead of for loop in java 8