在Java中, 泛型必须使用引用类型, 而不能使用基本类型。 所以要表示基本类型的列表或者数组时, 必须使用对应基本类型的引用类型, 如int
对应Integer
, long
对应Long
等, 在基本类型与引用类型可以自动地装箱与拆箱, 但是会有一些性能损失。
在Java 8的Stream API中提供了of
方法,如果传入基本类型的参数,内部其实得到的是一个引用类型的Stream。如下面代码
1 2 |
// 得到的是Integer类型的 Stream Stream<Integer> stream = Stream.of(1, 2, 3); |
因此, Java 8的提供了一些专门针对基本类型优化的API,如 IntStream
, LongStream
, DoubleStream
, 应该优先使用它们。
定义
定义基本类型的Stream, 可以使用IntStream
, LongStream
, DoubleStream
的接口静态方法of
, range
, empty
, 下面为例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// 创建一个空的 IntStream IntStream empty = IntStream.empty(); // 创建包含基本类型1, 2, 3的 IntStream IntStream intStream = IntStream.of(1, 2, 3); // 创建一个包含1到9的 IntStream IntStream range = IntStream.range(1, 10); // 创建一个包含1到10的 IntStream IntStream rangeClosed = IntStream.rangeClosed(1, 10); // 创建一个包含3的 IntStream IntStream generated = IntStream.generate(() -> 3); // 得到一个无限循环的 IntStream, 值为 1, 3, 5, 7 ... IntStream infinite = IntStream.iterate(1, operand -> operand + 2); |
也可以基于 int 数组创建 IntStream, 如
1 2 3 4 5 |
int[] array = new int[]{1, 2, 3, 4, 5}; // 包含整个数组的IntStream IntStream arrayStream = Arrays.stream(array); // 包含数组的索引位置2开始,4结束(不包含)的IntStream IntStream rangeArray = Arrays.stream(array, 2, 4); |
使用
基本类型的Stream,内部使用的都是与基本类型相关的接口函数来进行操作, 进而避免装箱成相应的引用类型, IntStream
主要有以下几个操作方法
filter方法
filter
方法于过滤Stream中的数据,它接收一个 IntPredicate
接口, 它是一个 int -> boolean
的接口函数, 例子代码如下
1 2 |
// 输出 2, 4, 6 IntStream.of(1, 2, 3, 4, 5, 6, 7).filter(elem -> elem % 2 == 0).forEach(System.out::println); |
map 方法
map
方法主要是对Stream的元素进行某种映射,转换成另一个基本类型的值, 它接收一个 IntUnaryOperator
接口, 它是一个 int -> int
的函数接口,例子代码如下:
1 2 |
// 输出 10, 20, 30, 40, 50, 60, 70 IntStream.of(1, 2, 3, 4, 5, 6, 7).map(elem -> elem * 10).forEach(System.out::println); |
mapToObj 方法
mapToObj
方法主要是将Stream中的元素进行装箱操作, 转换成一个引用类型的值, 它接收一个 IntFunction
接口, 它是一个 int -> R
的函数接口, 例子代码如下:
1 2 |
// 输出a1, a2, a3, a4, a5, a6, a7 IntStream.of(1, 2, 3, 4, 5, 6, 7).mapToObj(elem -> "a" + elem).forEach(System.out::println); |
mapToLong 方法
mapToLong
方法是将Stream中的 元素转换成基本类型long
, 它接收一个 IntToLongFunction
接口, 它是一个 int -> long
的函数接口, 例子代码如下
1 2 |
// 输出 100, 200, 300, 400, 500, 600, 700 IntStream.of(1, 2, 3, 4, 5, 6, 7).mapToLong(elem -> elem * 100L).forEach(System.out::println); |
mapToDouble 方法
mapToDouble
方法是将Stream中的 元素转换成基本类型double
, 它接收一个 IntToDoubleFunction
接口, 它是一个 int -> double
的函数接口, 例子代码如下
1 2 |
// 输出 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1 IntStream.of(1, 2, 3, 4, 5, 6, 7).mapToDouble(elem -> elem + 0.1).forEach(System.out::println); |
min 方法
min
方法获取Stream中最小的元素, 它返回 OptionalInt
类型, 它是一个int版的Optional
, 同样是为了避免拆箱装箱操作。 示例代码如下
1 2 |
// 输出 1 System.out.println(IntStream.of(1, 2, 3, 4).min().getAsInt()); |
summaryStatistics 方法
summaryStatistics
方法主要是获取Stream中元素的统计信息, 它返回 IntSummaryStatistics
, 示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 |
IntSummaryStatistics summary = IntStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).summaryStatistics(); // 输出 1 System.out.println(summary.getMin()); // 输出 10 System.out.println(summary.getMax()); // 输出 55 System.out.println(summary.getSum()); // 输出 10 System.out.println(summary.getCount()); // 输出 5.5 System.out.println(summary.getAverage()); |
此外, 还有 flatMap
, distinct
, sorted
, peek
, limit
, skip
, forEach
, reduce
, collect
, anyMatch
, allMatch
, noneMatch
等方法, 与Stream
的方法都差不多。