我试图将此转换为
String r = "";
for ( Persona p : list ) {
r += p.lastName;
}
要stream().filter.collect()
表单,但我想知道如何使用一个lambda表达式(不是方法引用)来编写collect
。我找不到一个很好的例子。
这就是我所拥有的
class B {
public static void main( String ... args ) {
List<Person> p = Arrays.asList(
new Person("John", "Wilson"),
new Person("Scott", "Anderson"),
new Person("Bruce", "Kent"));
String r;
String s = p.stream()
.filter( p -> p.lastName.equals("kent"))
.collect((r, p) -> r += p.lastName);/// ?????
}
}
class Person {
String name;
String lastName;
public Person( String name, String lastName ) {
this.name = name;
this.lastName = lastName;
}
}
我发现的所有示例都使用方法引用,而我 认为 应该有一种简单的方法来编写lambda表达式。
答案 0 :(得分:4)
假设您不想使用Collectors.joining()
这样的现成收藏家,您确实可以创建自己的收藏家。
但是,正如javadoc所指出的那样,collect()需要3个功能接口实例作为参数,或者需要收集器。所以你不能只将一个lambda表达式传递给collect()。
假设你想使用第一个版本,取3个lambda表达式,你会注意到,通过读取javadoc,结果必须是一个可变对象,并且String不可变。所以你应该使用StringBuilder。例如:
StringBuilder s =
p.stream()
.filter( p -> p.lastName.equals("kent"))
.map(p -> p.lastName)
.collect(StringBuilder::new,
StringBuilder::append,
StringBuilder::append);
这使用方法引用,但所有方法引用都可以写为lambda表达式。以上相当于
StringBuilder s =
p.stream()
.filter( p -> p.lastName.equals("kent"))
.map(p -> p.lastName)
.collect(() -> new StringBuilder(),
(stringBuilder, string) -> stringBuilder.append(string),
(stringBuilder1, stringBuilder2) -> stringBuilder1.append(stringBuilder2));
答案 1 :(得分:2)
您还可以使用.reduce()
功能,它比收集更容易阅读。
String s = p.stream()
.filter( p -> p.lastName.equals("kent"))
.reduce("", (acc, p) -> acc + p.lastName(), String::concat);
带有StringBuilder
的版本:
StringBuilder s = p.stream()
.filter( p -> p.lastName.equals("kent"))
.reduce(new StringBuilder(), (acc, p) -> acc.append(p.lastName()), StringBuilder::append);
答案 2 :(得分:1)
也许您正在设想reduce
操作而不是收集,这将允许您使用您设想的lambda表达式。例如,
String s = persons.stream()
.map( (s1, str) -> s1.concat(str) )
.reduce("", String::concat);
当然,这是一项练习。字符串连接效率低下,因此最好使用collect(Collectors.joining())
,它使用StringBuffer
作为累加器。