Java使用lambda表达式示例收集

时间:2016-04-06 21:03:08

标签: java lambda java-stream collect

我试图将此转换为

 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表达式。

3 个答案:

答案 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作为累加器。