1.Stream的由来
Java8引入了全新的Stream API,这里的Stream和I/O流不同,更像是Iterator的集合类,但行为和集合类不同。Stream API的引入在于弥补Java函数式编程的缺陷,可以用很少代码完成很多的功能。借助Lambda表达式,可以提高编程效率和可读性。它是对于集合功能的增强,专注于对集合对象进行各种高效,非常便利的聚合操作,或者大批量数据操作。同时提供了串行和并行两种操作,充分利用多核处理的优势,通过fork/join操作来拆分任务和加速处理过程。
2.Stream的介绍
Stream如同一个迭代器,单向,不可重复,只可以便利一次。但是Stream支持并行,数据源可以无限。
操作流的步骤是:获取一个数据源(source)→ 数据转换→执行操作获取想要的结果,每次转换原有 Stream 对象不改变,返回一个新的 Stream 对象(可以有多次转换),这就允许对其操作可以像链条一样排列,变成一个管道。
对Stream操作分为两种:
3.Stream的使用
Stream的使用过程就是实现filter-reduce-map的过程,产生一个最终结果。集合类新增的Stream方法用于把集合变成Stream,然后通过filter,map等操作实现stream的变换,还有forEach来完成元素的迭代。
3.1 Stream的创建
3.1.1使用Stream静态方法来创建Stream
of方法
//使用of方法
Stream integerStream = Stream.of(1, 2, 3, 5);
Stream stringStream = Stream.of("meituan");
generator方法:生成一个无限长度的Stream,其元素的生成是通过给定的Supplier(这个接口可以看成一个对象的工厂,每次调用返回一个给定类型的对象)
Stream.generate(new Supplier() {
@Override
public Double get() {
return Math.random();
}
});
Stream.generate(() -> Math.random());
Stream.generate(Math::random);
iterate
方法:
Stream.iterate(1, item -> item + 1).limit(10).forEach(System.out::println);
3.1.2通过Collection子类获取Stream对象
public interface Collection extends Iterable {
//其他方法省略
default Stream stream() {
return StreamSupport.stream(spliterator(), false);
}
}
需要注意的是,对于基本数值类型,有三种对应的包装类型,IntStream,LongStream,DoubleStream
3.2 Stream的Intermidiate操作
有map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
//map,一对一
List output = Arrays.asList("hi", "hello").stream().
map(String::toUpperCase).
collect(Collectors.toList());
//flatMap,一对多
Stream> inputStream = Stream.of(
Arrays.asList(1),
Arrays.asList(2, 3),
Arrays.asList(4, 5, 6)
);
Stream outputStream = inputStream.
flatMap((childList) -> childList.stream());
//filter,过滤
Integer[] sixNums = {1, 2, 3, 4, 5, 6};
Integer[] evens =
Stream.of(sixNums).filter(n -> n%2 == 0).toArray(Integer[]::new);
//peek,每个元素执行操作并返回一个新的 Stream
Stream.of("one", "two", "three", "four")
.filter(e -> e.length() > 3)
.peek(e -> System.out.println("Filtered value: " + e))
.map(String::toUpperCase)
.peek(e -> System.out.println("Mapped value: " + e))
.collect(Collectors.toList());
//limit,返回Stream前n个元素,skip,扔掉前n个元素
Stream.of(1, 2, 3, 4).limit(2).forEach(System.out::println);
3.3 Stream的Terminal操作
有forEach、toArray、reduce、collect、max、count、anyMatch、findFirst等
//forEach
Integer[] nums = {1, 2, 3};
Stream.of(nums).forEach(num -> System.out.println(num));
//toArray
Integer[] target = Stream.of(1, 2, 3).toArray(Integer[]::new);
//collect
Stream.of("one", "two", "three", "four")
.filter(e -> e.length() > 3)
.peek(e -> System.out.println("Filtered value: " + e))
.map(String::toUpperCase)
.peek(e -> System.out.println("Mapped value: " + e))
.collect(Collectors.toList());
//anyMatch/allMatch/nonMatch
boolean isBig = Stream.of(1, 100, 1000).allMatch(n -> n > 99);
4.自己生成流
通过实现 Supplier 接口,你可以自己来控制流的生成。把 Supplier 实例传递给 Stream.generate() 生成的 Stream,默认是串行(相对 parallel 而言)但无序的(相对 ordered 而言)。
Random seed = new Random();
Supplier random = seed::nextInt;
Stream.generate(random).limit(10).forEach(System.out::println);
//Another way
IntStream.generate(() -> (int) (System.nanoTime() % 100)).
limit(10).forEach(System.out::println);