Jdk8中Stream流的使用,让你脱离for循环

Wesley13
• 阅读 596

学习要求:知道一点儿函数式接口和Lambda表达式的基础知识,有利于更好的学习。

1.先体验一下Stream的好处

需求:给你一个ArrayList用来保存学生的成绩,让你打印出其中大于60的成绩。

  1. public static void main(String[] args) {

  2. ArrayList<Integer> arrList = new ArrayList<>();

  3. for (int i = 0; i < 100; i++) {

  4. arrList.add((int) (Math.random() * 100));

  5. }

  6. printValue1(arrList);

  7. }

  • 解决方案一:当然就是遍历这个ArrayList,然后使用if判断一下,如果其大于60,就将其输出,代码如下:
  1. private static void printValue1(ArrayList<Integer> arrList) {

  2. for (Integer i : arrList) {

  3. if (i > 60) {

  4. System.out.printf("%d ",i);

  5. }

  6. }

  7. }

  • 解决方案二:使用Stream流操作,只需要一行代码
  1. /**

  2. * 使用Stream操作

  3. *

  4. * @param arrList

  5. */

  6. private static void printValue2(ArrayList<Integer> arrList) {

  7. arrList.stream().filter(i -> i > 60).forEach(System.out::println);

  8. }

2.什么是Stream流?

在Jdk1.8中引入了stream流的概念,这个“流”并不同于IO中的输入和输出流,它是Jdk中的一个类,具体位置在:java.util.stream.Stream 关于它的操作主要分为三种:获取流、中间操作、最终操作

2.1 如何获取流?

所谓获取流,就是将其他对象(非Stream对象)转为Stream对象。只有两类对象可能转化为Stream对象,分别是:

  • 数组(这个数组中的元素必须是引用类型)
  1. Integer[] iArr = {12, 14, 15, 15, 17, 19, 22};

  2. Stream<Integer> stream1 = Stream.of(iArr);

  • 集合
  1. List<T> list = new ArrayList<T>();

  2. Stream<T> stream = list.stream();

2.2 中间操作(返回的是一个新的Stream对象)

从上边获取这个流对象时,我们就可以这个Stream对象进行操作,在执行结束操作前,可以无限次的执行这个操作。在开发工具中可以看到这个类的源码,它的主要有以下几种操作:

细心的话,你会发现,这个类的大多数方法中的参数全都是一个函数式接口(具体可以看上一篇文章),所以这就是为什么可以使用Lambda表达式的原因

  • map 将一种类型的值转换成另外一种类型,并返回一个新的Stream
  1. // 将集合中的字符串装换成大写形式

  2. Stream<String> stream0 = Stream.of("a", "b", "hello")

  3. .map(new Function<String, String>() {

  4. @Override

  5. public String apply(String s) {

  6. return s.toUpperCase();

  7. }

  8. });

`//上边的代码可以使用Lambda表达式简写为如下格式`


 
  1. Stream <String> stream = Stream.of("a", "b", "hello")

  2. .map(s -> s.toUpperCase());

所以,请一定要懂得Lambda表达式的操作

  • filter 遍历数据并检查、过滤其中的元素
  1. Stream<String> stream1 = Stream.of("a", "abc", "abcdefg")

  2. .filter(value -> value.length() > 1);

  • flatMap 可用Stream替换值,然后将多个Stream连接成一个Stream,会将之前生成Stream流的每一个元素更换为一个新的Stream对象。
  1. Stream <Integer> stream2 = Stream.of(1, 2)

  2. .flatMap(numbers -> Stream.of(5, 6, 6, 7, 8));

上边代码会生成的Stream中,会将1,2替换为5,6,7,8,5,6,7,8

  • 其他的常见操作还有:
  1. stream.limit(5) //限制,只取前几个元素

  2. .skip(1) //跳过,表示跳过前几个元素

  3. .distinct() //去重

  4. .sorted() //自然排序

  5. .sorted(Integer::compareTo)//自定义排序

2.3 最终操作

最终操作就是达到我们想要的结果,包括打印、转为其他对象(主要是集合,还有函数式接口的子类对象)等。只能执行一次,执行完闭后,不能再执行其他操作。

  • reduce 一般用于计算累加的,如下代码
  1. // 获取累加的值,reduce第一个参数是初始值

  2. Integer count = Stream.of(1, 2, 3)

  3. .reduce(0, (o1, o2) -> o1 + o2);

  4. System.out.println(count);//6

  • collect 将流转换为其他形式。参数是传入Collectors的一些静态方法,比如以下:
  1. Set<Integer> collect = stream.collect(Collectors.toSet());

  2. List<Integer> collect2 = stream.collect(Collectors.toList());

  3. HashSet<Integer> collect1 = stream.collect(Collectors.toCollection(HashSet::new));

  4. List<Integer> list = Stream.of(1, 2)

  5. .collect(Collectors.toList());

  • forEach 遍历这个流对象中的元素
  1. Stream.of(1, 2).forEach(i -> System.out.print(i));

  2. System.out.println();

`  
//上边格式可以使用静态方法引用的方法简化`


 
  1. Stream .of(1, 2).forEach(System.out::print);

最后,写一个简单的例子,比较一下,我们使用之前的遍历操作和使用Stream流操作的简洁性与性能问题

相比之下 ,Stream流的操作要比使用迭代器操作慢一点儿,但是这是很小的差别

本文分享自微信公众号 - 小鱼与Java(Fish_Java)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Karen110 Karen110
2年前
​一篇文章总结一下Python库中关于时间的常见操作
前言本次来总结一下关于Python时间的相关操作,有一个有趣的问题。如果你的业务用不到时间相关的操作,你的业务基本上会一直用不到。但是如果你的业务一旦用到了时间操作,你就会发现,淦,到处都是时间操作。。。所以思来想去,还是总结一下吧,本次会采用类型注解方式。time包importtime时间戳从1970年1月1日00:00:00标准时区诞生到现在
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Stella981 Stella981
2年前
HIVE 时间操作函数
日期函数UNIX时间戳转日期函数: from\_unixtime语法:   from\_unixtime(bigint unixtime\, string format\)返回值: string说明: 转化UNIX时间戳(从19700101 00:00:00 UTC到指定时间的秒数)到当前时区的时间格式举例:hive   selec
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这