将 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);
请注意,使用 codePointAt
比 charAt
好得多,因为如果您的字符串以代理项对开头,使用 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,但使用 injectInto
和 StringBuilder
而不是 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();
我有以下 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);
请注意,使用 codePointAt
比 charAt
好得多,因为如果您的字符串以代理项对开头,使用 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,但使用 injectInto
和 StringBuilder
而不是 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();