Search code examples
javalambdajava-streamcollect

Java collect with lambda expression example


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.


Solution

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