前面两篇简单的介绍了Stream以及如何创建Stream,本篇就给大家说说stream有哪些用途,以及具体怎样使用。

再次介绍Stream

Stream 使用一种类似用于SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。 Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。 这种风格将要处理的元素集合看作一种流,流在管道中传输,并且可以在管道的节点上进行处理,比如筛选,排序,聚合等。

Stream两种操作

  • 中间操作(Intermediate Operations):中间操作会返回一个新的流,一个流可以后面跟随零个或多个intermediate操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后会返回一个新的流,交给下一个操作使用。这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历。而是在终端操作开始的时候才真正开始执行。
  • 终端操作(Terminal Operations):是指返回最终的结果。一个流只能有一个terminal操作,当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。Terminal操作的执行,才会真正开始流的遍历,并且会生成一个结果,或者一个 side effect。

中间操作方法分类:

  • filter()
  • map()
  • flatMap()
  • distinct()
  • sorted()
  • peek()
  • limit()
  • skip()

终端操作方法分类:

  • forEach()
  • forEachOrdered()
  • toArray()
  • reduce()
  • collect()
  • min()
  • max()
  • count()
  • anyMatch()
  • allMatch()
  • noneMatch()
  • findFirst()
  • findAny()

中间操作代码实例详解

1、filter(): 返回结果生成新的流中只包含满足筛选条件的数据。

// 1、filter,返回大于2的元素集合
List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> result = nums.stream().filter(n -> n > 2).collect(Collectors.toList());
System.out.println(result);

运行结果:[3, 4, 5]

2、map():将流中的元素进行再次加工形成一个新流,流中的每一个元素映射为另外的元素。

// 2、map:返回元素的大写类型和哈希值
List<String> mzc = Arrays.asList("ma", "zhi", "chu");
List<String> mzcUpperCase = mzc.stream().
map(n -> n.toUpperCase()).
collect(Collectors.toList());
List<Integer> mzcHashCode = mzc.stream().map(n -> n.hashCode()).collect(Collectors.toList());
System.out.println("mzcUpperCase:"+mzcUpperCase+" ----- mzcHashCode:"+mzcHashCode);

运行结果:

mzcUpperCase:[MA, ZHI, CHU] ----- mzcHashCode:[3476, 120571, 98480]

示例场景:取出商品的所有id,就可以这样写(伪代码):

List<Product> productList = productService.selectAll();

List<Integer> pIds = productList.stream().map(p->p.getId).collect(Collectors.toList());

这样就可以拿到所有商品id的集合。

3、flatMap():扁平化映射,它具体的操作是将多个stream连接成一个stream,这个操作是针对类似多维数组的,比如集合里面包含集合,相当于降维作用。

flatMap是将流中的每个元素都放到一个流中,最后将所有的流合并成一个新流,所有流对象中的元素都合并到这个新生成的流中返回。

// flatMap:将多层集合中的元素取出来,放到一个新的集合中去
List<Integer> num1 = Arrays.asList(1, 2, 3);
List<Integer> num2 = Arrays.asList(4, 5, 6);
List<Integer> num3 = Arrays.asList(7, 8, 9);
List<List<Integer>> lists = Arrays.asList(num1, num2, num3);
Stream<Integer> outputStream = lists.stream().flatMap(l -> l.stream());
List<Integer> flatMapResult = outputStream.sorted().collect(Collectors.toList());
System.out.println(flatMapResult);

运行结果:[1, 2, 3, 4, 5, 6, 7, 8, 9]

示例场景:取出所有部门人员的姓名,就可以这样写(伪代码):

// 1、取出所有部门

List<Department> departments = ...;

// 2、这个时候可以利用flatMap先将所有部门的所有人员汇聚起来

List<Person> persons = departments.stream.flatMap(d->d.getPersonList()).collect(Collectors.toList());

// 3、再利用map()方法取出

4、distinct():顾名思义,将流中的元素去重之后输出。

        List<String> mzc = Stream.of("ma","zhi","chu","zhi","shuo","ma")
.distinct()
.collect(Collectors.toList());
System.out.println(mzc);

运行结果:[ma, zhi, chu, shuo]

5、sorted():这个很简单了,顾名思义,将流中的元素按照自然排序方式进行排序。

// sorted:自然顺序排序
List<Integer> nums = Arrays.asList(1, 3, 5, 6, 8, 2);
List<Integer> sortedNum = nums.stream().sorted().collect(Collectors.toList());
System.out.println(sortedNum); // sorted:降序排序
List<Integer> sortedNum2 = nums.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
System.out.println(sortedNum2); // sorted:使用Comparator
List<Integer> sortedNums3 = nums.stream().sorted(Comparator.comparing(n -> n)).collect(Collectors.toList());
System.out.println(sortedNums3); // 不用stream直接顺序排序
nums.sort(Comparator.comparing(Integer::intValue));
System.out.println(nums); //不用stream直接降序排序
nums.sort(Comparator.comparing(Integer::intValue).reversed());
System.out.println(nums);

运行结果:

[1, 2, 3, 5, 6, 8]

[8, 6, 5, 3, 2, 1]

[1, 2, 3, 5, 6, 8]

[1, 2, 3, 5, 6, 8]

[8, 6, 5, 3, 2, 1]

6、peek():对流中每个元素执行操作,并返回一个新的流,返回的流还是包含原来流中的元素。

// peek():
String[] arr = new String[]{"a","b","c","d"};
Arrays.stream(arr)
.peek(System.out::println) //a,b,c,d
.count(); // peek()+filter()
Stream.of("ma", "zhi", "chu")
.filter(e -> e.length() > 2)
.peek(e -> System.out.println(e))
.collect(Collectors.toList());

运行结果:

a

b

c

d

zhi

chu

7、limit():顾名思义,返回指定数量的元素的流。返回的是Stream里前面的n个元素。

// limit():取出100中的前十个
List<Integer> limitNum = IntStream.range(1,100).limit(10)
.boxed()
.collect(Collectors.toList());
System.out.println(limitNum); // limit():取出前4个单词
List<String> words = Arrays.asList("ma", "zhi", "chu", "wait", "you", "follow");
List<String> limitWord = words.stream().limit(4).collect(Collectors.toList());
System.out.println(limitWord);

运行结果:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

[ma, zhi, chu, wait]

8、skip():和limit()相反,将前几个元素跳过(取出)再返回一个流,如果流中的元素小于或者等于n,就会返回一个空的流。

// skip():跳过前面三个单词再返回
List<String> words = Arrays.asList("ma", "zhi", "chu", "wait", "you", "follow");
List<String> skipWord = words.stream().limit(4).collect(Collectors.toList());
System.out.println(skipWord); // skip():跳过全部单词再返回
List<String> emptyWord = words.stream().skip(6).collect(Collectors.toList());
System.out.println(emptyWord); // skip():跳过超过单词长度的数目再返回
List<String> emptyWord2 = words.stream().skip(10).collect(Collectors.toList());
System.out.println(emptyWord);

运行结果:

[91, 92, 93, 94, 95, 96, 97, 98, 99]

[ma, zhi, chu, wait]

[]

[]


上面讲了Stream流中间操作的使用详解,希望能给大家带来帮助,如果有用,还麻烦点个在看,或者分享给需要的小伙伴,独乐乐不如众乐乐,谢谢!

因为考虑篇幅太长,大家看起来可能会有点累,所以Stream的终端操作使用详解,串行化、并行化区别,以及stream流总结放到后面的文章中。如果你还想了解更多其他方面的知识,欢迎留言鼓励,我会争取越写越好,越写越全面。

Java8 Stream中间操作使用详解的更多相关文章

  1. Java8 Stream终端操作使用详解

    话不多说,自己挖的坑自己要填完,今天就给大家讲完Java8中Stream的终端操作使用详解.Stream流的终端操作主要有以下几种,我们来一一讲解. forEach() forEachOrdered( ...

  2. Java 8系列之Stream的基本语法详解

    本文转至:https://blog.csdn.net/io_field/article/details/54971761 Stream系列: Java 8系列之Stream的基本语法详解 Java 8 ...

  3. Java基础学习总结(33)——Java8 十大新特性详解

    Java8 十大新特性详解 本教程将Java8的新特新逐一列出,并将使用简单的代码示例来指导你如何使用默认接口方法,lambda表达式,方法引用以及多重Annotation,之后你将会学到最新的API ...

  4. 005-Scala数组操作实战详解

    005-Scala数组操作实战详解 Worksheet的使用 交互式命令执行平台 记得每次要保存才会出相应的结果 数组的基本操作 数组的下标是从0开始和Tuple不同 缓冲数组ArrayBuffer( ...

  5. ASP.NET 操作Cookie详解 增加,修改,删除

    ASP.NET 操作Cookie详解 增加,修改,删除 Cookie,有时也用其复数形式Cookies,指某些网站为了辨别用户身份而储存在用户本地终端上的数据(通常经过加密).定义于RFC2109.它 ...

  6. 在telnet下操作memcache详解(操作命令详解)

    这篇文章主要介绍了在telnet下操作memcache详解,telnet下的memcache操作命令详解,需要的朋友可以参考下 在定位问题.测试等时候经常需要对memcache的数据进行一些操作,但是 ...

  7. Spring Data操作Redis详解

    Spring Data操作Redis详解 Redis是一种NOSQL数据库,Key-Value形式对数据进行存储,其中数据可以以内存形式存在,也可以持久化到文件系统.Spring data对Redis ...

  8. SQL Server 表的管理_关于数据增删查改的操作的详解(案例代码)

    SQL Server 表的管理_关于数据增删查改的操作的详解(案例代码)-DML 1.SQL INSERT INTO 语句(在表中插入) INSERT INTO 语句用于向表中插入新记录. SQL I ...

  9. SQL Server 表的管理_关于表的操作增删查改的操作的详解(案例代码)

    SQL Server 表的管理_关于表的操作增删查改的操作的详解(案例代码) 概述: 表由行和列组成,每个表都必须有个表名. SQL CREATE TABLE 语法 CREATE TABLE tabl ...

随机推荐

  1. bootstrap网格系统.html

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  2. unity 之 自定义弹出框

    一.弹出框的搭建: 布局如图:Message为整个父物体,并且添加UiMessage代码.panel为遮罩. MessageBox为整个提示框,Panel为标题,ok为确定按钮,cancel为取消按钮 ...

  3. python购物车小案例

    python购物车小案例# 案列描述:有一个小型水果店里面有水果(苹果:¥8/kg,香蕉:¥5/kg,芒果:¥15/kg,葡萄:¥12/kg),客户带了100元钱进店选购水果.# 1.客户输入相应序号 ...

  4. Web for pentester_writeup之Code injection篇

    Web for pentester_writeup之Code injection篇 Code injection(代码注入) Example 1 <1> name=hacker' 添加一个 ...

  5. K近邻(k-Nearest Neighbor,KNN)算法,一种基于实例的学习方法

    1. 基于实例的学习算法 0x1:数据挖掘的一些相关知识脉络 本文是一篇介绍K近邻数据挖掘算法的文章,而所谓数据挖掘,就是讨论如何在数据中寻找模式的一门学科. 其实人类的科学技术发展的历史,就一直伴随 ...

  6. [考试反思]1027csp-s模拟测试90:自我

    其实这套题很好. 但是这次,在T1爆炸的同时,T2和T3并没有出现能弥补的表现. 在AK仍然存在的同时,我居然连一个AC都没有. 所以最后就是一无是处的一场. 考试结束前估分:100+100+30=2 ...

  7. spring session源码解析

    模块划分 core部分代码 存储实现部分部分: jdbc实现 具体存储的实现类 例如:org.springframework.session.jdbc.JdbcOperationsSessionRep ...

  8. 消息中心 - Laravel的Redis队列(一)

    前言 Laravel的队列可以用在轻量级的队列需求中.比如我们系统中的短信.邮件等功能,这些功能有一些普遍的特征,异步.重试.并发控制等.Laravel现在主要支持的队列服务有Null.Sync.Da ...

  9. STL库学习笔记(一)——什么是STL?

    小明是一个很牛逼的程序员,在国际标准化组织工作. 他现在正在设计新一代的C++标准,标准中有一个待实现的函数:findMax(),这个函数要求使用者输入任何类型的数据,他都能找到最大的一个. 于是他想 ...

  10. PyCharm安装及使用教程

    1  PyCharm下载 PyCharm的下载安装非常简单,可以直接到Jetbrains公司官网下载,具体步骤如下: (1)打开Pycharm官网http://www.jetbrains.com,选择 ...