一、 数值流
- 在操作数值流的过程中,其实隐藏着一个问题:
装箱成本
,每个原始类型都必须装箱成一个包装类型,如:
Stream<Integer> integerStream = Stream.of(1, 2, 3); Integer sum = integerStream.reduce(0, Integer::sum);
二、 数值特化流(基本类型流)
- 为了避免不必要的拆箱和装箱,Java8引入了三个原始类型特化流接口:
IntStream
,LongStream
和DoubleStream
,将流中的元素特化为int
,long
和double
,避免暗含的装箱成本。并且,在这三个特化接口中,提供了常用的数值规约方法,可以方便地进行数值相关的操作,如min
,max
,sum
等。如果需要将基本类型特化流再转换成引用类型流,也有相应的方法支持。 - 引用类型流映射成值类型流
- 常用方法是
mapToInt()
,mapToLong()
和mapToDouble
,以及flatMapToXxx
... - 上述方法的返回值不再是Stream<T>,而是相应的数值类型流,如
IntStream
。
IntStream intStream = integerStream.mapToInt(x -> x); // 求和 int intSum = intStream.sum(); // 计算最大值 OptionalInt intMax = integerStream.mapToInt(x -> x).max(); // 计算最小值 OptionalInt intMin = integerStream.mapToInt(x -> x).min();
- 数值类型流转换成引用类型流
- 使用
.boxed()
装箱方法
boxed()
方法实际上内部调用的都是mapToObj()
方法
IntStream intStream = integerStream.mapToInt(x -> x); Stream<Integer> boxedIntegerStream = intStream.boxed(); Stream<Long> boxedLongStream = LongStream.range(1, 10).boxed();
三、 关于OptionalInt
- 在介绍数值流的时候,可以注意到数值流提供的几个规约方法的返回值:
- 如
sum()
返回的是int
,因为sum
存在默认值0. - 而
max()
和min()
的返回值都是OptionalInt
,没有默认值,因为设置默认值为0是一种错误的做法。而对于这三种特化流,有三个参数化的Optional类:OptionalInt
,OptionalLong
和OptionalDouble
。
// 注意range(1,1)生成的是一个空的流 OptionalInt optionalInt = IntStream.range(1, 1).max(); // 空的流无法获取到最大值 optionalInt.ifPresent(x -> System.out.println("最大值为:" + x)); // 当无结果时,返回一个默认值 System.out.println("默认最大值:" + optionalInt.orElse(1));
默认最大值:1
四、 数值范围
- 为了方便地生成一定范围内的数字,Java8提供了可以作用于
IntStream
和LongStream
的范围方法:range(start,end)
和rangeClose(start,end)
,区别是rangeClose()
会包含end
这个值。
// 生成1~100,并求和 System.out.println(IntStream.rangeClosed(1, 100).sum());