Java 8中的原始类型流
1. 简介
Stream API 是 Java 8 中添加的关键特性之一。 简而言之,API 允许我们通过提供声明式 API 来方便且更高效 地处理集合和其他元素序列。
2. 原始流
流主要处理对象集合而不是原始类型。 幸运的是,为了提供一种使用三种最常用的原始类型(int、long和double)的方法,标准库包括三个原始专用实现:IntStream、LongStream和DoubleStream。 原始流受到限制主要是因为装箱开销,并且因为在许多情况下为其他原始流创建专用流并不是那么有用。
3. 算术运算
让我们从一些有趣的方法开始,这些方法用于大量使用的算术运算,例如min、max、sum和average:
int[] integers = new int[] {20, 98, 12, 7, 35};
int min = Arrays.stream(integers)
.min()
.getAsInt(); // returns 7
现在让我们逐步浏览上面的代码片段以了解发生了什么。 我们使用java.util.Arrays.stream(int[])创建了我们的IntStream,然后使用min()方法获取最小整数作为java.util.OptionalInt,最后调用getAsInt()来获取int值。 创建IntStream的另一种方法是使用IntStream.of(int…)。*max()*方法将返回最大的整数:
int max = IntStream.of(20, 98, 12, 7, 35)
.max()
.getAsInt(); // returns 98
接下来——要获得整数的总和,我们只需调用sum()方法,我们不需要使用getAsInt(),因为它已经将结果作为int值返回:
int sum = IntStream.of(20, 98, 12, 7, 35).sum(); // returns 172
我们调用average()方法来获取整数值的平均值,正如我们所见,我们应该使用getAsDouble()因为它返回一个double类型的值。
double avg = IntStream.of(20, 98, 12, 7, 35)
.average()
.getAsDouble(); // returns 34.4
4. 范围
我们还可以基于范围创建IntStream:
int sum = IntStream.range(1, 10)
.sum(); // returns 45
int sum = IntStream.rangeClosed(1, 10)
.sum(); // returns 55
如上面的代码片段所示,有两种方法可以创建整数值范围 range()和rangeClosed()。 不同之处在于range()的结尾是独占的,而在rangeClosed()中是包含的。 Range 方法仅适用于IntStream和LongStream。
我们可以将 range 用作 for-each 循环的一种奇特形式:
IntStream.rangeClosed(1, 5)
.forEach(System.out::println);
将它们用作 for-each 循环替换的好处是我们还可以利用并行执行:
IntStream.rangeClosed(1, 5)
.parallel()
.forEach(System.out::println);
与这些花哨的循环一样有用的是,使用传统的 for 循环而不是函数式循环来进行简单的迭代仍然更好,因为在某些情况下具有简单性、可读性和性能。
5. 装箱和拆箱
有时我们需要将原始值转换为它们的包装器等价物。 在这些情况下,我们可以使用*boxed()*方法:
List<Integer> evenInts = IntStream.rangeClosed(1, 10)
.filter(i -> i % 2 == 0)
.boxed()
.collect(Collectors.toList());
我们还可以从包装类流转换为原始流:
// returns 78
int sum = Arrays.asList(33,45)
.stream()
.mapToInt(i -> i)
.sum();
我们总是可以使用mapToXxx和flatMapToXxx方法来创建原始流。