半年前开始试着使用Java的新特性,给我印象最深的就是Stream流和Optional。其中Stream提高了看法效率,让代码看起来十分清爽。

为什么要使用流?

摘要中已经说明了,为了提高开发效率。流可以帮助我们高效操作集合,流帮助我们通过流水线的方式对集合进行删减合并排序修改,并最终返回我们想要的元素数据或统计数据。流水线的意思是说,一批元素不需要等待全部元素都完成某步操作,才进行下步操作,而是可以尽早进行下步操作,就好像流水线工厂一样,这为流高效运作提供了基础。流还有一个内部迭代的概念,就是把for循环显示迭代隐藏起来了,这样可以更方便的并行开发

流的使用

准备

在使用流之前需要做些准备,首先说明两个概念:中间操作终端操作中间操作就好比生产车间的一步一步元素处理,每步处理之后,里面的元素样式或者数据结构可能发生改变了,但是它还是流。终端操作就好比产品生产完了,要打包装箱,变成最终消费者可见的最终形态,此时,它已经是产品,不再是流了。

接着为了演示操作,先模拟几条数据

List<JSONObject> menu = new ArrayList<>();
menu.add(new JSONObject().putOpt("name","宫保鸡丁").putOpt("price","28"));
menu.add(new JSONObject().putOpt("name","鱼香肉丝").putOpt("price","30"));
menu.add(new JSONObject().putOpt("name","肉夹馍").putOpt("price","6"));
menu.add(new JSONObject().putOpt("name","煎饼").putOpt("price","6"));

常用的中间操作

filter

filter应该是Stream操作里面最常见的了,过滤器顾名思义就是过滤数据用的,filter的参数可以是lambda表达式。

//比如下面这句话,就是得到所有价格小于10的食物,得到的还是流。
//stream()方法将集合转成流
menu.stream().filter(jsonObject -> jsonObject.getInt("price")<10);

distinct 、 limit 和 skip

distinct是去重,limit是截取前几个元素,skip是跳过前多少个元素。

List<Integer> integerList = new ArrayList<>();
integerList.add(1);
integerList.add(1);
integerList.add(2);
integerList.add(3);
integerList.stream()
.distinct()//经过去重,流还剩1、2、3
.skip(1)//跳过第一个元素,流中还有2、3
.limit(1);//截取第一个元素,流中还剩2

map

map映射,上面的filter是将元素筛选,map则是改变元素的样式。比如,我们想要知道所有小于10块食物的名字。

menu.stream()
.filter(jsonObject -> jsonObject.getInt("price")<10)//此时还是jsonObject
.map(jsonObject -> jsonObject.getStr("name"));//此时变成了String

flatMap

流的合并,可以将多个数组合并操作,这样返回元素不是流,而是具体元素本身了。

Stream.of(menu,foreignMenu)//此时元素是流 List<Stream>
.flatMap(x -> x.stream())//此时元素是jsonObject List<jsonObject>
.map(jsonObject -> jsonObject.getStr("name"))
.distinct();

常用的终端方法

allMatch、anyMatch、noneMatch、findFirst和findAny

方法 含义
allMatch 检查谓词是否匹配所有元素
anyMatch 检查谓词是否至少匹配一个元素
noneMatch 确保流中没有任何元素与给定的谓词匹配
findFirst 查找第一个符合条件的元素
findAny 将返回当前流中的任意元素
//前三个方法都是返回boolean类型
boolean allMatchBool = menu.stream()
.allMatch(jsonObject -> jsonObject.getInt("price") < 10);
boolean noneMatchBool = menu.stream()
.noneMatch(jsonObject -> jsonObject.getInt("price") < 10);
boolean anyMatchBool = menu.stream()
.anyMatch(jsonObject -> jsonObject.getInt("price") < 10);

上面个方法返回的都是boolean类型,findFirst、findAny返回的都是元素。

//关于Optional,先不关心,总之是元素就对了
Optional<JSONObject> first = menu.stream().findFirst();
Optional<JSONObject> any = menu.stream().findAny(); System.out.println(first.get().toString());
System.out.println(any.get().toString()); //输出
//{"price":"28","name":"宫保鸡丁"}
//{"price":"28","name":"宫保鸡丁"}

以上两个方法,只要找到符合条件的数据,流就提前结束了。为什么都是输出第一个元素,却要实现有两个方法呢?因为并行,findAny在并行方面限制会少一些。

reduce

最开始的时候说了,最终的返回值可以是元素集合,也可以是统计数据(或者说归纳),比如说元素求和。假设我们需要menu中所有食品各要一份需要花多少钱。

Optional<Integer> price = menu.stream()//List<JsonObject>
.map(jsonObject -> jsonObject.getInt("price"))//先将元素转成数字List<Integer>
.reduce((x, y) -> x + y);
System.out.println(price.get());

max和min

这个好理解,就是最大值和最小值嘛。效果类似于

.reduce(Integer::max)
.reduce(Integer::min)

常用流汇总

其中没有展示sorted、count这个都好理解。至于collect这个后面讲,用的比较多。

流的转化

除了对象流(Stream)以外,还有一些类型流,比如说 IntStream(以 IntStream 举例,其他类似)上面求和返回的是Optional对象,那可以直接返回Integer类型吗?

//使用映射方法mapToInt()就ok了
int price = menu.stream()//Stream
.mapToInt(jsonObject -> jsonObject.getInt("price"))//IntStream
.sum();
//类型流转化回对象流,可以使用boxed()
IntStream intStream = menu.stream()
.mapToInt(jsonObject -> jsonObject.getInt("price"));
Stream<Integer> boxed = intStream.boxed();
//当然了IntStream中有很多int类型操作的方法,就不一一举例了,源码打开一看,见名知意

收集器

前面讲的常用的中间操作,返回值都是流,还有一些中断操作,返回值都是Optional或者数值。可别忘了Stream最开始的初衷是为了解决集合操作问题。最终转化成集合使用的中断操作collect,参数是接口 Collector,里面有众多转化方法。

转换成集合

最常用的莫非toList() 这个方法了,将返回结果变成List。

List<JSONObject> list = menu.stream()
.filter(jsonObject -> jsonObject.getInt("price") < 10)
.collect(Collectors.toList());
//当然还有toSet()等等,触类旁通

字符串拼接

比较常用,就是字符串链接了。使用joining()方法

String s = menu.stream()
.filter(jsonObject -> jsonObject.getInt("price") < 10)
.map(jsonObject -> jsonObject.getStr("name"))
.collect(Collectors.joining(","));

分组

根据提供的属性分组,使用 groupingBy() ,为了方便说明,给上面各种食品一个type值:

List<JSONObject> menu = new ArrayList<>();
menu.add(new JSONObject().putOpt("name","宫保鸡丁").putOpt("price","28").putOpt("type","good"));
menu.add(new JSONObject().putOpt("name","鱼香肉丝").putOpt("price","30").putOpt("type","good"));
menu.add(new JSONObject().putOpt("name","肉夹馍").putOpt("price","6").putOpt("type","normal"));
menu.add(new JSONObject().putOpt("name","煎饼").putOpt("price","6").putOpt("type","normal")); Map<String, List<JSONObject>> type = menu.stream()
.collect(Collectors.groupingBy(jsonObject -> jsonObject.getStr("type")));
System.out.println(type);
//输出
//{normal=[{"price":"6","name":"肉夹馍","type":"normal"}, {"price":"6","name":"煎饼","type":"normal"}], good=[{"price":"28","name":"宫保鸡丁","type":"good"}, {"price":"30","name":"鱼香肉丝","type":"good"}]}

与分组类似的还有一个方法 partitioningBy (),分区,不过它的参数位于是boolean类型。

再来看看Java的新特性——Stream流的更多相关文章

  1. 这可能是史上最好的 Java8 新特性 Stream 流教程

    本文翻译自 https://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/ 作者: @Winterbe 欢迎关注个人微信公众 ...

  2. Java 8 新特性-Stream更优雅的处理集合入门

    Java 8 新特性之--Stream 一. 简单介绍 Stream是Java 8提出了的一种新的对集合对象功能的增强.它集合Lambda表达式,对集合提供了一些非常便利,高效的操作,使得代码具有非常 ...

  3. Java8新特性 Stream流式思想(一)

    遍历及过滤集合中的元素使用传统方式遍历及过滤集合中的元素package cn.com.zq.demo01.Stream.test01.Stream; import java.util.ArrayLis ...

  4. Java1.8新特性 - Stream流式算法

    一. 流式处理简介   在我接触到java8流式数据处理的时候,我的第一感觉是流式处理让集合操作变得简洁了许多,通常我们需要多行代码才能完成的操作,借助于流式处理可以在一行中实现.比如我们希望对一个包 ...

  5. Java8新特性 Stream流式思想(二)

    如何获取Stream流刚开始写博客,有一些不到位的地方,还请各位论坛大佬见谅,谢谢! package cn.com.zq.demo01.Stream.test01.Stream; import org ...

  6. 再来看看Java的新特性——其他新特性

    关于剩余Java8新特性知识点总结,包含:默认方法.Optional.CompletableFuture.时间相关. 默认方法 默认方法皆在帮助Java新功能可以兼容低版本JDK已开发的程序. 比如说 ...

  7. java8 新特性Stream流的应用

    作为一个合格的程序员,如何让代码更简洁明了,提升编码速度尼. 今天跟着我一起来学习下java 8  stream 流的应用吧. 废话不多说,直入正题. 考虑以下业务场景,有四个人员信息,我们需要根据性 ...

  8. Java8新特性 Stream流式思想(三)

    Stream接口中的常用方法 forEach()方法package cn.com.cqucc.demo02.StreamMethods.Test02.StreamMethods; import jav ...

  9. JDK8新特性---stream流

    项目上用到了stream流,找篇blog,转载一下,介绍下Stream流的用法. 1 流概述  流是 JDK8 新增的成员,允许以声明性方式处理数据集合,可以把 Stream 流看作是遍历数据集合的一 ...

随机推荐

  1. 二十、CI框架数据库操作之查看生产的sql语句

    一.代码如下: 二.我们访问一下: 三.我们对比一下数据库内容 不忘初心,如果您认为这篇文章有价值,认同作者的付出,可以微信二维码打赏任意金额给作者(微信号:382477247)哦,谢谢.

  2. javascript 连续赋值(连等运算)问题研究

    前几天看到一个javascript 连续赋值的问题,运行了一下,结果出乎意料,发现这里的水真的有点深啊,连续赋值的底层机制,没有一本前端书籍有详细介绍的,自己做实验研究了一下,先来看结果: var a ...

  3. Flexslider插件实现图片轮播、文字图片相结合滑动切换效果

    插件下载: 点击下载 密码: fbeg Flexslider具有以下特性: 支持滑动和淡入淡出效果. 支持水平.垂直方向滑动. 支持键盘方向键控制. 支持触控滑动. 支持图文混排,支持各种html元素 ...

  4. Hour of Code|京东云邀您一起,“码”上行动

    "如果我并不希望成为一名程序员,那么为什么需要学习编程呢?" 相信很多人对于现在鼓励从小就学习编程的趋势都在心里问过这样的一个问题.在回答这个问题前,先和大家分享一个小故事吧. 1 ...

  5. linux搭建mariadb,windows2008搭建iis+php+wordpress

    centos ip:192.168.101 windows ip :192.168.102 centos配置: [root@ml ~]# yum -y install mariadb-server # ...

  6. opencv vs2013提示缺少Qedit.h问题

    #pragma include_alias( "dxtrans.h", "qedit.h" ) #define __IDxtCompositor_INTERFA ...

  7. 2018CCPC吉林赛区 hdu6555~hdu6566

    2018CCPC吉林赛区(重现赛)- 感谢北华大学 A 基础数论. #include<bits/stdc++.h> using namespace std; typedef long lo ...

  8. .NET技术-5.0. NETCORE设置返回数据字段的大小写

    .NET技术-5.0. NETCORE设置返回数据字段的大小写 问题来源于我写了一个接口,接口的返回类型是JsonResult,但是对接之后反应返回结果的首字母全小写了, 后来查了写资料返现.net ...

  9. 当我们进行综合和I/O布局后会发生什么QwQ

    基于的平台是Vivado 2018.2 本文主要以一个简单的半加器加器(组合逻辑为例)学习vivado的综合,I/O配置的一些内容. 本人小白,记一些自己的理解. 任务: 分析Log文件. 布局I/O ...

  10. pip速度慢解决办法

    pip速度慢解决办法 sudo pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple 注意加不加sudo是 ...