将 for 循环转换为 concat String 为 lambda 表达式

Convert a for loop to concat String into a lambda expression

我有以下 for 循环,它遍历字符串列表并将每个单词的第一个字符存储在 StringBuilder 中。我想知道如何将其转换为 lambda 表达式

StringBuilder chars = new StringBuilder();
for (String l : list) {
    chars.append(l.charAt(0));
}  

假设您之后在 StringBuilder 上调用 toString(),我认为您只是在将每个字符串映射到单字符子字符串后寻找 Collectors.joining()

String result = list
    .stream()
    .map(s -> s.substring(0, 1))
    .collect(Collectors.joining());

示例代码:

import java.util.*;
import java.util.stream.*;

public class Test {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("foo");
        list.add("bar");
        list.add("baz");
        String result = list
            .stream()
            .map(s -> s.substring(0, 1))
            .collect(Collectors.joining());
        System.out.println(result); // fbb
    }
}

请注意使用 substring 而不是 charAt,因此我们仍然可以使用字符串流。

无需创建许多中间 String 对象,您可以这样做:

StringBuilder sb = list.stream()
                       .mapToInt(l -> l.codePointAt(0))
                       .collect(StringBuilder::new, 
                                StringBuilder::appendCodePoint, 
                                StringBuilder::append);

请注意,使用 codePointAtcharAt 好得多,因为如果您的字符串以代理项对开头,使用 charAt 您可能会得到不可预测的结果。

有很多方法可以做到这一点 - 最简单的选择:坚持添加到 StringBuilder 并执行此操作:

StringBuilder chars = new StringBuilder();

list.forEach(l -> chars.append(l.charAt(0)));

以下是针对此问题的三种不同解决方案。每个解决方案首先过滤空字符串,否则可能会抛出 StringIndexOutOfBoundsException

此解决方案与 Tagir 的解决方案相同,只是添加了用于过滤空字符串的代码。我将其包含在这里主要是为了与我提供的其他两个解决方案进行比较。

List<String> list =
    Arrays.asList("the", "", "quick", "", "brown", "", "fox");
StringBuilder builder = list.stream()
    .filter(s -> !s.isEmpty())
    .mapToInt(s -> s.codePointAt(0))
    .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append);
String result = builder.toString();
Assert.assertEquals("tqbf", result);

第二种解决方案使用7.0版本中添加的Eclipse Collections, and leverages a relatively new container type called CodePointAdapter

MutableList<String> list =
    Lists.mutable.with("the", "", "quick", "", "brown", "", "fox");
LazyIntIterable iterable = list.asLazy()
    .reject(String::isEmpty)
    .collectInt(s -> s.codePointAt(0));
String result = CodePointAdapter.from(iterable).toString();
Assert.assertEquals("tqbf", result);

第三个解决方案再次使用 Eclipse Collections,但使用 injectIntoStringBuilder 而不是 CodePointAdapter

MutableList<String> list =
    Lists.mutable.with("the", "", "quick", "", "brown", "", "fox");
StringBuilder builder = list.asLazy()
    .reject(String::isEmpty)
    .collectInt(s -> s.codePointAt(0))
    .injectInto(new StringBuilder(), StringBuilder::appendCodePoint);
String result = builder.toString();
Assert.assertEquals("tqbf", result);

注意:我是 Eclipse Collections 的提交者。

使用方法参考的简单方法:

List<String> list = Arrays.asList("ABC", "CDE");
StringBuilder sb = new StringBuilder();

list.forEach(sb::append);

String concatString = sb.toString();