Java 8-Stream API-数值流

int colories=menu.stream()
        .map(Dish::getCalories)
        .reduce(0,Integer::sum);

这段有一个暗含的装箱成本。每个Integer都必须拆箱成一个原始类型,再进行求和。

map方法会生成一个Stream<T>,虽然流中的元素是Integer类型,但Stream接口没有定义sum方法。为什么没有呢?比如,你只有一个像menu那样的Stream<Dish>,把各种菜加起来是没有任何意义的。

Stream API提供了原始类型流特化,专门支持处理数值流的方法。

IntStream,DoubleStream和LongStream,分别将流中的元素特化为int,long和double,从而避免了暗含的装箱成本。每个接口都带来了进行常用数值归约的新方法,比如sum和max。

1.映射到数值流

mapToInt,mapToDouble和mapToLong。这些方法和前面说的map方法的工作方式一样,只是他们返回的是一个特化流,而不是Stream

int colories=menu.stream()
        .mapToInt(Dish::getCalories)//返回一个IntStream
        .sum();

如果流时空的,sum默认返回0。IntStream还支持其他的方法,如max、min、average等。

2.转换回对象流

IntStream intStream=menu.stream().mapToInt(Dish::getColories);//将Stream转换为数值流
Stream<Integer> stream=intStream.boxed();//将数值流转换为Stream

3.默认值OptionalInt

如果没有元素的话,求和的时候返回0,这没有问题。但如果要计算IntStream中的最大元素,就得换个法子了,因为0是错误结果。如何区分没有元素的流和最大值真的是0的流呢?

Optional可以用Integer、String等引用类型。对于三种原始流特化,也分别有一个Optional原始类型特化版本:OptionalInt、OptionalDouble和OptionalLong。

OptionalInt maxCalories=menu.stream()
        .mapToInt(Dish::getColaries)
        .max();

现在,如果没有最大值的话,可以显示处理OptionalInt去定义一个默认值了

int max=maxCalories.orElse(1);

数值范围

比如,假设你想要生成1和100之间的所有数字。Java8引入了两个可以用于IntStream和LongStream的静态方法,帮助生成这种范围:range和rangeClosed。这两个方法都是第一个参数接收起始值,第二个参数接受结束值。但range是不包含结束值的,而rangeClosed则包含结束值。

IntStream evenNumbers=IntStream.rangeClosed(1,100)
    .filter(n->n%2==0);
System.out.println(evenNumbers.count());

这里用了rangeClosed方法来生成1到100之间的所有数字。它会产生一个流,然后你可以链接filter方法,只选出偶数。到目前为止还没有进行任何计算。最后,你对生成的流调用count。因为count是一个终端操作,所以它会处理流,并返回结果50,这正是1到100(包括两端)中所有偶数的个数。如果改用IntStream.range(1,100),则结果将会是49个偶数,因为range是不包含结束值的。

    原文作者:eaglezsx
    原文地址: https://blog.csdn.net/zsx157326/article/details/80886804
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞