繁体   English   中英

Java使用lambda表达式示例收集

[英]Java collect with lambda expression example

我试图转换这个

 String r = "";
 for ( Persona p : list ) {
    r += p.lastName;
 }

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

假设您不想使用任何现成的收集器,如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));

您还可以使用.reduce()函数,它比collect更容易阅读。

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

也许你正在设想一个reduce操作而不是一个collect,这将允许你使用像你想象的lambda表达式。 例如,

String s = persons.stream()
        .map( (s1, str) -> s1.concat(str) )
        .reduce("", String::concat);

当然,这是一项练习。 字符串连接效率低下,因此最好使用collect(Collectors.joining()) ,它使用StringBuffer作为累加器。

您可以省略使用此解决方案的映射:

Collector<Person, StringBuilder, String> collector = Collector.of(  
    StringBuilder::new,
    (buf, person) -> buf.append( person.lastName ),
    (buf1, buf2) -> {
      buf1.append( buf2 );
      return( buf1 );
    },
    buf -> buf.toString() 
  );

list.stream()
  .filter( p -> p.lastName.equals( "Kent" ) )
  .collect( collector );

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM