MENU

Java 8 学习笔记(二)Lambda与Stream

March 10, 2018 • Read: 327 • Java

实践数据如下,电影列表:包括名称、评分、时长、年份和演员列表。

Movie(name=无极, score=5.0, duration=121, year=2005, 
actorList=[Actor(name= 张东健, birthday=1972-03-07), Actor(name=张柏芝, birthday=1980-05-24), Actor(name=真田广之, birthday=1960-10-12), Actor(name=谢霆锋, birthday=1980-08-29), Actor(name=刘烨, birthday=1978-03-23)])

Movie(name=救火英雄, score=7.2, duration=115, year=2014, 
actorList=[Actor(name=谢霆锋, birthday=1980-08-29), Actor(name=余文乐, birthday=1981-11-13), Actor(name=任达华, birthday=1955-03-19), Actor(name=胡军, birthday=1968-03-18)])

Movie(name=喜剧之王, score=8.6, duration=85, year=1999, 
actorList=[Actor(name=周星驰, birthday=1962-06-22), Actor(name=张柏芝, birthday=1980-05-24), Actor(name=莫文蔚, birthday=1970-06-02)])

Movie(name=大话西游之月光宝盒, score=8.9, duration=87, year=1995, 
actorList=[Actor(name=周星驰, birthday=1962-06-22), Actor(name=吴孟达, birthday=1952-01-02), Actor(name=罗家英, birthday=1947-08-27), Actor(name=蓝洁瑛, birthday=1963-04-27), Actor(name=莫文蔚, birthday=1970-06-02)])

Stream化

计算评分不小于8.0的电影数量,在jdk 1.8 之前可以使用for循环或者Iterator来实现

int count = 0;
BigDecimal score = new BigDecimal("8.0");
for (Movie movie : movieList) {
    if (movie.getScore().compareTo(score) >= 0) {
        count++;
    }
}
System.out.println(count);

在jdk 1.8 中,调用stream()方法创建一个Stream,使用filter方法过滤,并不会改变列表的内容,而是返回一个新的Stream,最后调用count()方法计算个数。

long count = movieList.stream().filter(movie -> movie.getScore().compareTo(score) >= 0).count();
System.out.println(count);

在Stream接口中,包含了filter、map、flatMap、distinct等一系列方法,它们都返回Strea类型对象,可以链式调用多次转化;也包含了count、anyMatch、findFirst等聚合求值方法。

惰性求值

惰性求值(Lazy evaluation,也称作call-by-need)是在将表达式赋值给变量(或称作绑定)时并不计算表达式的值,而在变量第一次被使用时才进行计算。

Stream操作分为两种,惰性求值及早求值,返回值是Stream的是惰性求值,返回其他或返回空的则是及早求值

movieList.stream().filter(movie -> {
    System.out.println("score:" + movie.getScore());
    return movie.getScore().compareTo(score) >= 0;
});

以上例子只是刻画了stream,并没有做任何操作,所以并不会有打印score。

而下面调用了count方法的例子则打印了4行内容

movieList.stream().filter(movie -> {
    System.out.println("score:" + movie.getScore());
    return movie.getScore().compareTo(score) >= 0;
}).count();

打印内容如下:

score:5.0
score:7.2
score:8.6
score:8.9

惰性求值中的参数直到需要时才会进行计算。实际上是从末尾开始反向执行的。它会判断自己需要返回什么,并继续向后执行来确定要这样做需要哪些值。

下面的例子中,多增加了limit(1),在过滤评分不小于8.0后只取一个对象,

movieList.stream().filter(movie -> {
    System.out.println("score:" + movie.getScore());
    return movie.getScore().compareTo(score) >= 0;
}).limit(1).count();

打印了3行内容:

score:5.0
score:7.2
score:8.6

这也印证了惰性求值的执行过程;因为limit(1),所以在filer了一个满足的对象后,就不再继续执行fiter了。惰性求值可以减少计算数据的步骤,提高效率。

默认方法

Last Modified: July 21, 2019