lambda数值流

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

Java 8引入了三个原始类型特化流接口来解决这个问题IntStream、DoubleStream、LongStream,分别将流中的元素特化为int、long和double,从而避免了暗含的装箱成本。每个接口都带来了进行常用数值归约的新方法。比如对数值流求和的sum,找到最大元素的max。此外还有在必要时再把它们转换回对象流的方法。要记住的是,这些特化的原因并不在于流的复杂性,而是装箱造成的复杂性——即类似int和Integer之间的效率差异。

映射到数值流:

流转换为特化版本的常用方法是mapToInt、mapToDouble和mapToLong。这些方法和前面说的map方法的工作方式一样,只是它们返回的是一个特化流,而不是Stream<T>。例如下面的案例,获取菜单中每个菜的卡路里之和。注意,如果流是空的,sum默认返回0。


int sumCalories = menu.stream()    //←─返回一个Stream<Dish> 
.mapToInt(Dish::getCalories)    //←─返回一个IntStream 
.sum();//←─可以调用sum、max、min等方法。

转换回对象流:

一旦有了数值流,你可能会想把它转换回非特化流即对象流。例如,IntStream上的操作只能产生原始整数,IntStream的map操作接受的Lambda必须接受int并返回int。但是你可能想要生成另一类值,比如Dish。为此,你需要访问Stream接口中定义的那些更广义的操作。要把原始流转换成一般流可以使用boxed方法,在需要将数值范围装箱成为一个一般流时,boxed尤其有用。


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

默认值OptionalInt:

计算IntStream中的最大元素,就得换个法子了,因为0是错误的结果。Optional可以用Integer、String等参考类型来参数化。对于三种原始流特化,也分别有一个Optional原始类型特化版本:OptionalInt、OptionalDouble和OptionalLong。

找到IntStream中的最大元素,可以调用max方法,它会返回一个OptionalInt:


OptionalInt maxCalories = menu.stream().mapToInt(Dish::getCalories).max();
int max = maxCalories.orElse(1);    ←─如果没有最大值的话,显式提供一个默认最大值

数值范围:

和数字打交道时,有一个常用的东西就是数值范围。ava 8引入了两个可以用于IntStream和LongStream的静态方法,帮助生成这种范围:range和rangeClosed。这两个方法都是第一个参数接受起始值,第二个参数接受结束值。但range是不包含结束值的,而rangeClosed则包含结束值。


IntStream evenNumbers = IntStream.rangeClosed(1, 100)   // ←─表示范围[1, 100] 共100个                               
.filter(n -> n % 2 == 0);   // ←─一个从1到100的偶数流
System.out.println(evenNumbers.count()); //   ←─从1 到100 有50个偶数
IntStream evenNumbers = IntStream.range(1, 100)//  ←─range不包含结束值
System.out.println(evenNumbers.count()); //   ←─从1 到100 有49个偶数

版权声明:
作者:苍狗长风
链接:https://www.develophm.com/index.php/lambda%e6%95%b0%e5%80%bc%e6%b5%81/445/
来源:开发之家
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
< <上一篇
下一篇>>