此章节继续介绍其它Stream API用法
一 归约
归约将流中的所有元素反复结合起来,归约成一个值。用函数式的术语来说,可以称为折叠。
1、元素求和
reduce接受两个参数:
1、一个是初始值
2、一个是BinaryOperator将两个元素结合成一个新值,比如:(a,b) -> a+b
举例求和:
public static void testReduce() {
List<Integer> integers = Arrays.asList(1, 2, 3, 45, 6);
Integer reduce = integers.stream().reduce(0, (a, b) -> a + b);
System.out.println(reduce);
}
reduce还有个重载方法不接受初始值,返回的是一个Optional。
2、最大值和最小值
给定两个元素返回一个最大值的lambda,reduce会考虑新值和流中的下一个元素,并产生一个最大值,直到流消费结束。
举例说明:
public static void testReduceMax() {
List<Integer> integers = Arrays.asList(1, 2, 3, 45, 6);
Optional<Integer> reduce = integers.stream().reduce(Integer::max);
System.out.println(reduce.get());
Optional<Integer> reduce1 = integers.stream().reduce(Integer::min);
System.out.println(reduce1.get());
}
使用reduce的好处,迭代被内部迭代抽象了,内部实现得以选择并行执行reduce操作。
二、数值流
使用reduce可以计算流中元素的总和,但是这样是有问题,有一个暗含的装箱成本,每个integer都必须拆箱成一个原始类型,再求和,可以直接调用sum:
public static void testReduceSum() {
List<Integer> integers = Arrays.asList(1, 2, 3, 45, 6);
int sum = integers.stream().mapToInt(d -> d.intValue()).sum();
System.out.println(sum);
}
1、映射数值流
java8引入了三个原始类型流解决装箱拆箱问题:IntStream、DoubleStream、LongStream。每个接口中都有对数sum,max,min,average等方法。
例:
public static void testReduceSum() {
List<Integer> integers = Arrays.asList(1, 2, 3, 45, 6);
int sum = integers.stream().mapToInt(d -> d.intValue()).sum();
OptionalInt max = integers.stream().mapToInt(d -> d.intValue()).max();
OptionalInt min = integers.stream().mapToInt(d -> d.intValue()).min();
OptionalDouble average = integers.stream().mapToInt(d -> d.intValue()).average();
System.out.println(sum);
}
2、转换对象流
将数值流转化成对象流调用方法,调用boxed方法。
public static void testReduceObj() {
List<Integer> integers = Arrays.asList(1, 2, 3, 45, 6);
IntStream intStream = integers.stream().mapToInt(d -> d.intValue());
Stream<Integer> boxed = intStream.boxed();
}
3、数值范围
IntStream、DoubleStream、LongStream生成流范围range不包含结束值,rangeClosed包含结束值。
public static void testRangeClosed() {
IntStream intStream = IntStream.rangeClosed(0, 100).filter(d -> d % 2 == 0);
long count = intStream.count();
System.out.println(count);
}
三、构建流
创建流的方法有很多,值序列、数据组、文件创建流。
1、由值创建流
静态方法Stream.of。例:
public static void testStreamof() {
Stream<String> java8 = Stream.of("java8", "lambda", "in action");
}
}
2、由数组创建流
Arrays.stream
int[] i = new int[]{1,3,34};
IntStream stream = Arrays.stream(i);
3、由文件生成流
java中用于处理文件的I/O操作已更新,以便用Stream API。
java.nio.file.Files中有很多静态方法会返回一个stream。一个很有用的方法Files.lines。例:
Stream<String> lines = Files.lines(Paths.get("xx.txt"));
4、由函数生成流
Stream.iterate和Stream.generate可以创建无限流。
Stream.iterate,iterate接受一个初始值为0,接受参数(final T seed, final UnaryOperator f)
例:
public static void testiterate() {
Stream<Integer> iterate = Stream.iterate(0, n -> n + 2);
}
此方法生成一个正偶数的流。
Stream.generate,generate也可以生成一个无限流,但generate不是依次 对每个新生成的值应用函数。接受参数Supplier s
Stream<Double> generate = Stream.generate(Math::random);