I was trying to convert this
String r = "";
for ( Persona p : list ) {
r += p.lastName;
}
To stream().filter.collect()
form, but I want to know how to write the collect
with a lambda expression (not method references). I couldn't find a good example.
This is what I have
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;
}
}
All the examples I find are using method references whereas I think there should be an easy way to write a lambda expression instead.
Assuming you don't want to use any ready-made collector like Collectors.joining()
, you could indeed create your own collector.
But, as the javadoc indicates, collect() expects either 3 functional interface instances as argument, or a Collector. So you can't just pass a single lambda expression to collect().
Assuming you want to use the first version, taking 3 lambda expressions, you'll note, by reading the javadoc, that the result must be a mutable object, and String is not mutable. So you should instead use a StringBuilder. For example:
StringBuilder s =
p.stream()
.filter( p -> p.lastName.equals("kent"))
.map(p -> p.lastName)
.collect(StringBuilder::new,
StringBuilder::append,
StringBuilder::append);
This uses method references, but all method references can be written as lambda expressions. The above is equivalent to
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));