Java 8 发布至今也已经好几年过去,如今 Java 也已经向 11 迈去,但是 Java 8 作出的改变可以说是革命性的,影响足够深远,学习 Java 8 应该是 Java 开发者的必修课。

今天给大家带来 Java 8 Stream 讲解,为什么直接讲这个,是因为只要你学完,立刻就能上手,并能让它在你的代码中大展身手。

值得注意的是:学习 Stream 之前必须先学习 lambda 的相关知识。本文也假设读者已经掌握 lambda 的相关知识

本篇文章主要内容:

  • 介绍 Stream 以及 Stream 是如何处理集合的
  • 介绍 Stream 与集合的关系与区别

本篇文章主要是让大家能够理解 Stream,理解它的基本原理,理解我们为什么需要使用 Stream 以及它的好处,而具体的实战环节我会在下篇文章中讲解。

一. 什么是 Stream

Stream 中文称为 “流”,通过将集合转换为这么一种叫做 “流” 的元素序列,通过声明性方式,能够对集合中的每个元素进行一系列并行或串行的流水线操作

换句话说,你只需要告诉流你的要求,流便会在背后自行根据要求对元素进行处理,而你只需要 “坐享其成”。

二. 流操作

整个流操作就是一条流水线,将元素放在流水线上一个个地进行处理。

其中数据源便是原始集合,然后将如 List 的集合转换为 Stream 类型的流,并对流进行一系列的中间操作,比如过滤保留部分元素、对元素进行排序、类型转换等;最后再进行一个终端操作,可以把 Stream 转换回集合类型,也可以直接对其中的各个元素进行处理,比如打印、比如计算总数、计算最大值等等

很重要的一点是,很多流操作本身就会返回一个流,所以多个操作可以直接连接起来,我们来看看一条 Stream 操作的代码:

如果是以前,进行这么一系列操作,你需要做个迭代器或者 foreach 循环,然后遍历,一步步地亲力亲为地去完成这些操作;但是如果使用流,你便可以直接声明式地下指令,流会帮你完成这些操作。

有没有想到什么类似的?是的,就像 SQL 语句一样, select username from user where id = 1,你只要说明:“我需要 id 是 1 (id = 1)的用户(user)的用户名(username )”,那么就可以得到自己想要的数据,而不需要自己亲自去数据库里面循环遍历查找。

三. 流与集合

什么时候计算

Stream 和集合的其中一个差异在于什么时候进行计算。

一个集合,它会包含当前数据结构中所有的值,你可以随时增删,但是集合里面的元素毫无疑问地都是已经计算好了的。

流则是按需计算,你可以想象一个水龙头,假设你需要一个奇数流,从 1 开始,那么这个水龙头会源源不断地流出你需要的数据,假设你只需要 10 个,那么这个流便会按需生成 10 个奇数,换句话来说,就是在用户要求的时候才会计算值,只要你需要,你便可以打开这个水龙头。

又比方说我们通过搜索引擎进行搜索,搜索出来的条目并不是全部呈现出来的,而且先显示最符合的前 10 条或者前 20 条,只有在点击 “下一页” 的时候,才会再输出新的 10 条。

再比方在线观看电影和你硬盘里面的电影,也是差不多的道理。

外部迭代和内部迭代

Stream 和集合的另一个差异在于迭代。

我们可以把集合比作一个工厂的仓库,一开始工厂比较落后,要对货物作什么修改,只能工人亲自走进仓库对货物进行处理,有时候还要将处理后的货物放到一个新的仓库里面。在这个时期,我们需要亲自去做迭代,一个个地找到需要的货物,并进行处理,这叫做外部迭代

后来工厂发展了起来,配备了流水线作业,只要根据需求设计出相应的流水线,然后工人只要把货物放到流水线上,就可以等着接收成果了,而且流水线还可以根据要求直接把货物输送到相应的仓库。这就叫做内部迭代,流水线已经帮你把迭代给完成了,你只需要说要干什么就可以了(即设计出合理的流水线)。

Java 8 引入 Stream 很大程度是因为,流的内部迭代可以自动选择一种合适你硬件的数据表示和并行实现;而以往程序员自己进行 foreach 之类的时候,则需要自己去管理并行等问题。

一次性的流

流和迭代器类似,只能迭代一次。

Stream<String> stream = list.stream().map(Person::getName).sorted().limit(10);
List<String> newList = stream.collect(toList());
List<String> newList2 = stream.collect(toList());

上面代码中第三行会报错,因为第二行已经使用过这个流,这个流已经被消费掉了

四. 关于并行

我们通过 list.stream() 将 List 类型转换为流类型,我们还可以通过 list.parallelStream() 转换为并行流。

并行流就是把内容分成多个数据块,使用不同的线程分别处理每个数据块的流。这也是流的一大特点,要知道,在 Java 7 之前,并行处理数据集合是非常麻烦的,你得自己去将数据分割开,自己去分配线程,必要时还要确保同步避免竞争。

Stream 让程序员能够比较轻易地实现对数据集合的并行处理,但要注意的是,不是所有情况的适合,有些时候并行甚至比顺序进行效率更低,而有时候因为线程安全问题,还可能导致数据的处理错误,这些我会在下一篇文章中讲解。


相关阅读

猜你喜欢

你的关注就是我不断发文最大的动力

简洁又快速地处理集合——Java8 Stream(上)的更多相关文章

  1. 简洁又快速地处理集合——Java8 Stream(下)

    上一篇文章我讲解 Stream 流的基本原理,以及它与集合的区别关系,讲了那么多抽象的,本篇文章我们开始实战,讲解流的各个方法以及各种操作 没有看过上篇文章的可以先点击进去学习一下 简洁又快速地处理集 ...

  2. Java8 新特性之集合操作Stream

    Java8 新特性之集合操作Stream Stream简介 Java 8引入了全新的Stream API.这里的Stream和I/O流不同,它更像具有Iterable的集合类,但行为和集合类又有所不同 ...

  3. 快速掌握Java8 Stream函数式编程技巧

    函数式编程优势 "函数第一位",即函数可以出现在任何地方. 可以把函数作为参数传递给另一个函数,还可以将函数作为返回值. 让代码的逻辑更清晰更优雅. 减少了可变量(Immutabl ...

  4. JAVA8 Stream集合操作:中间方法和完结方法

    StreamLambda为java8带了闭包,这一特性在集合操作中尤为重要:java8中支持对集合对象的stream进行函数式操作,此外,stream api也被集成进了collection api, ...

  5. Java8 Stream —— 更丝滑的集合操作方式

    一.概念 Stream是一种可供流式操作的数据视图有些类似数据库中视图的概念它不改变源数据集合如果对其进行改变的操作它会返回一个新的数据集合. 总的来讲它有三大特性:在之后我们会对照着详细说明     ...

  6. java代码之美(2)---Java8 Stream

    Stream 第一次看到Stream表达式就深深把我吸引,用它可以使你的代码更加整洁而且对集合的操作效率也会大大提高,如果你还没有用到java8的Stream特性,那就说明你确实out啦. 一.概述 ...

  7. 何用Java8 Stream API进行数据抽取与收集

    上一篇中我们通过一个实例看到了Java8 Stream API 相较于传统的的Java 集合操作的简洁与优势,本篇我们依然借助于一个实际的例子来看看Java8 Stream API 如何抽取及收集数据 ...

  8. Java8 Stream新特性详解及实战

    Java8 Stream新特性详解及实战 背景介绍 在阅读Spring Boot源代码时,发现Java 8的新特性已经被广泛使用,如果再不学习Java8的新特性并灵活应用,你可能真的要out了.为此, ...

  9. 如何通过 IntelliJ IDEA 来提升 Java8 Stream 的编码效率

    本文翻译整理自:https://winterbe.com/posts/2015/03/05/fixing-java-8-stream-gotchas-with-intellij-idea 作者:@Wi ...

随机推荐

  1. maven+springMVC+mybatis+easyUI管理用户增删改查

    1.项目演示图 2.项目简单介绍 项目分为两个projectdomain和manager.project结构例如以下图所看到的.当中domain是Maven javaproject主要完毕对数据库的操 ...

  2. c18---数组和指针

    // // main.c // day09 #include <stdio.h> int main(int argc, const char * argv[]) { ; int *numP ...

  3. oracle scott趣事

    Oracle里面是scott是个什么用户呢? 这个就要追朔到Oracle的创业阶段了, 1977年6月,埃里森,Bob Miner和Ed Oates在硅谷共同创办了一家名为软件开发实验室(Softwa ...

  4. Memcached 与 Redis 的关键性能指标比较

    性能对比: Redis 只使用单核,而 Memcached 可以使用多核,所以平均每一个核上 Redis在存储小数据时比 Memcached 性 能更高. 而在 100k 以上的数据中,Memcach ...

  5. JavaScript函数传参

    函数传参一: <html> <head> <meta charset="utf-8"> <title>无标题文档</title ...

  6. axis2 1.7.1使用教程

    写在前面 本文只说Axis2的用法. 1.下载与部署 需要下载两个文件: 下载地址:http://mirrors.cnnic.cn/apache/axis/axis2/java/core/1.7.1/ ...

  7. boost的单例模式

    template <typename T> struct singleton_default {   private:     struct object_creator     {    ...

  8. VC++抛出自定义编译期异常的指令

    #error 即可, 抛出消息是 #pragma message 最新的还有static_assert有一些用 一下子忘了网上居然搜不到...尝试了 关键字vc++.vc.vs.msvc +  抛出编 ...

  9. RabbitMQ学习之Flow Control

    当RabbitMQ发布消息速度快于消费速度或者系统资源不足时,RabbitMQ将降低或阻断发布消息速度,以免服务器资源饱满而宕机,可以通过rabbitmqctl和web管理页面查看连接的状态为flow ...

  10. mach-o格式分析

    0x00 摘要 人生无根蒂,飘如陌上尘. 分散逐风转,此已非常身. — 陶渊明 <杂诗> mach-o格式是OS X系统上的可执行文件格式,类似于windows的PE与linux的ELF, ...