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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31456898/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 11:08:29  来源:igfitidea点击:

Convert a for loop to concat String into a lambda expression

javacollectionslambdajava-8java-stream

提问by Faktor 10

I have the following for loop which iterates through a list of strings and stores the first character of each word in a StringBuilder. I would like to know how can I transform this to a lambda expression

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

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

采纳答案by Jon Skeet

Assuming you call toString()on the StringBuilderafterwards, I think you're just looking for Collectors.joining(), after mapping each string to a single-character substring:

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

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

Sample code:

示例代码:

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
    }
}

Note the use of substringinstead of charAt, so we still have a stream of strings to work with.

注意使用substring代替charAt,所以我们仍然有一个字符串流可以使用。

回答by Tagir Valeev

Without creating many intermediate String objects you can do it like this:

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

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

Note that using codePointAtis much better than charAtas if your string starts with surrogate pair, using charAtyou may have an unpredictable result.

请注意,使用codePointAtcharAt字符串以代理对开头好得多,使用charAt可能会产生不可预测的结果。

回答by Fritz Duchardt

Tons of ways to do this - the most simple option: stick to adding to a StringBuilderand do this:

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

    final StringBuilder chars = new StringBuilder();

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

回答by Donald Raab

Here are three different solutions to this problem. Each solution filters empty strings first as otherwise StringIndexOutOfBoundsExceptionmay be thrown.

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

This solution is the same as the solution from Tagir with the added code for filtering empty strings. I included it here primarily to compare to the other two solutions I have provided.

此解决方案与来自 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);

The second solution uses Eclipse Collections, and leverages a relatively new container type called CodePointAdapterthat was added in version 7.0.

第二个解决方案使用Eclipse Collections,并利用了CodePointAdapter在 7.0 版中添加的一种名为的相对较新的容器类型。

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);

The third solution uses Eclipse Collections again, but with injectIntoand StringBuilderinstead of CodePointAdapter.

第三个解决方案再次使用 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);

Note: I am a committer for Eclipse Collections.

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

回答by Rahul Chauhan

Simple way using method reference :

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

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

list.forEach(sb::append);

String concatString = sb.toString();