Java系列-StreamApi

Java Stream 简介

Java8 中的 Stream 是对集合(Collection) 对象功能的增强,它专注于对集合对象进行各种便利、高效的聚合操作, 或者是大批量的数据操作。Stream Api 的引入是为了弥补 Java 函数式编程的不足。但是这些 Api 并没有在集合类实现, 而是定义了全新的Stream APi。有几个重要的原因:

  • 集合类的所有元素都存储在内存中,非常大的集合类将占据大量的内存,但是 Stream 只有在执行结束操作(terminal)的 时候才会真正的进行计算(稍后会提到)。

  • 另外还有集合类的迭代逻辑通常是通过 for 来负责的,但是 Stream 的迭代是隐含在对 Stream 的各种操作中,例如 map(), reduce()。

创建一个流有很多的方法,例如:

1
2
3
4

Collection.stream();
Collection.parallelStream();
Arrays.stream(T array) or Stream.of();

一个流可以进行多种操作,总的来说,流的操作分为三类:

  • 中间操作: 一个流可以有零个或者多个中间操作,是为了打开流,作出某种程度的数据映射和过滤,然后返回一个新的流(每次转 换原有的 Stream 对象不变,会返回转变后的一个新的对象),也就是说,进行这类操作并没有真正开始流的遍历,典型的中间操作 有:map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered。

  • 结束操作: 一个流只能有一个结束操作,进行这个操作之后,这个流也就结束了,无法进行其他的中间操作或者结束操作,也就是 说结束操作使得流进行了真正的遍历,典型的结束操作有:forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator。

  • 短路操作:因为 Stream 有另外的一个特性,就是 可以存在无限的流。而短路操作正是用来处理这些情况。对于中间操作,如果 接受的是一个无限大的 Stream, 短路操作可以帮助返回一个有限的新的 Stream。对于结束操作,如果接受的十一个无限大的 Stream,短路操作可以帮助在有限的时间内计算出结果,典型的短路操作有:anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit。

Java Stream 应用

一个简单的 Stream 例子:

1
2
3
4
5
6
7
8
9
public static void main(String[] args) {

List<Integer> numbers = Arrays.asList(1,45,9,34,78,19,65,76);

numbers.stream()
.filter((i) -> i%2 ==0)
.map((i) -> i * i)
.forEach(System.out::println);
}

生成一个无限流,并且取出有限的个数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class NumberStream implements Supplier<Long> {

long value = 0;

@Override
public Long get() {
this.value = this.value + 1;

return this.value;
}


public static void main(String[] args) {

Stream<Long> numbers = Stream.generate(new NumberStream());

numbers.map((x) -> x * x ).skip(100).limit(10).forEach(System.out::println);
}
}

微信公众号

© 2018 ray