Java基础:流Stream究竟有什么好的
今天随便聊聊Java 8 中新出现的流(Stream)。
流是用来批量处理数据集合的。而传统处理方法,是for或while循环、iterate迭代处理。
Java编程思想的作者对流的评价很高,他说:“流改变了 Java 编程的本质,而且带来了极大的提升。”
那流究竟给我们的编程带来了什么好处呢?主要有以下几点:
-
从我们最关心的效率上来说,在小数据量的情况下,流式处理是比循环和迭代处理慢一点,不过数据量小,对程序的效率基本没影响;当数据量大时,尤其使用了并行流时,效率是高于传统批量处理方式的。
-
流的编码优雅和简洁得多
- 它是属于声明式编程,相对于命令式编程而言。就是你要对数据集做什么,你直接告诉程序,具体的执行过程由程序自己内部完成。比如要求最大值,则使用 max()函数,要求和,使用 sum()函数,至于怎么max,怎么sum,不用你管,程序自己默默完成了。这样编码就非常简洁了。而命令式编程,需要你把具体的实现过程显式地写出来,相对而言非常繁琐
- 它往往和函数式编程方式相结合,让代码更加简练,非常的赏心悦目。
-
没有存储
具体说,就是不存储源数据内容和所有的中间值到内存(当然,也会存储一小部分需要的中间序列值,但是相对于容纳整个序列需要的内存是很小的)。这样如果数据量大,就大大节省了内存空间。比如读取一个文件内容,并分隔成一个个单词,然后筛选所有长度大于5的单词。传统做法是读取该文件的所有行到一个List,然后遍历每一行,对每一行分隔成一个个单词,然后筛选出符合条件的单词,保存到最终结果List中。
那么,流不需要把文件的所有行保存到内存中,只需要告诉它读取哪个文件,还有筛选条件,它就通过一系列计算步骤,直接将最终的单词保存到最终的结果List中了。
再举个具体的例子,你去菜市场买菜,一种方式是先把菜场的所有菜都搬回家,然后挑选出自己需要的菜装到菜篮子中,最后把其余的菜都扔掉;第二种方式是直接在菜场挑选出自己需要的菜装到篮子中,然后回家。显然第二种方式更简单,第二种方式就是流使用的方式。
也许你会很惊讶,因为现实生活中,没有哪个二货用第一种方法,但是对于程序而言,在数据量不是很大的情况下,它有足够的内存来使用方法一,并且也不会很慢。
所以,这一点也是提高了流的处理效率。 -
惰性求值
流是链式计算,往往有多个计算步骤。传统方式是先计算一步,得到结果,然后再计算下一步,得到下一个结果,以此类推。这样,每一步都要实际地去计算。而流,它不这样,它是先查看一共有多少个计算步骤,是否有短路操作,能否跳过一些计算步骤,最后不得不计算了,才开始计算。
因为这个特性,通过流可以表示很大的(甚至是无限大的)序列,而不用考虑内存是否足够。比如第一步,创建一个无限大的序列,第二步,用limit(10)函数,提取前面10个序列,一下子从处理无限大的序列,变成只需要处理10个序列值。
比如过滤、排序、映射、去重等流式操作,都是以这种方式处理的。