文章参考自博客:https://www.cnblogs.com/franson-2016/p/5593080.html

以及学习网站:how2java.cn

1.传统方式和聚合操作遍历数据的不同

传统遍历List的方式如下:

  1. for(Hero h:list){
  2. if(h.getAge()>50 && h.getId()<400)
  3. System.out.println(h.getName());
  4. }

而使用了聚合操作的方式如下:

  1. list
  2. .stream()
  3. .filter( h-> h.getAge()>50 && h.getId()<400)
  4. .forEach(h-> System.out.println(h.getName()));

2.Stream(流)是什么?

Stream是对集合的包装,通常和lambda一起使用。 使用lambdas可以支持许多操作,如 map, filter, limit, sorted, count, min, max, sum, collect 等等。 同样,Stream使用懒运算,他们并不会真正地读取所有数据,遇到像getFirst() 这样的方法就会结束链式语法。

Stream和Collection结构化的数据不同,Stream有一系列的元素

管道指的是一系列的聚合操作的总和

管道由三部分组成:管道源中间操作结束操作

(1)管道源: 其可以是一个集合,一个数组,一个生成器函数或一个I / O通道

  1. //管道源是一个集合
  2. list
  3. .stream()
  4. .forEach(h-> System.out.println(h.getName()));
  5.  
  6. //管道源是一个数组
  7. Hero array[] = list.toArray(new Hero[list.size()]);
  8.  
  9. Arrays.stream(array)
  10. .forEach(h-> System.out.println(h.getName()));

(2)零个或多个中间操作:  每个中间操作会返回一个流,如filter,中间操作时懒操作,不会真正遍历

中间操作有很多种,主要分为两种:

1.对元素进行筛选:filter(匹配),distinct(去除重复),sorted(自然排序)

sorted(Comparator)(指定排序),limit(保留),skip(忽略)

2.转为其他形式的流:mapToDouble(转为double的流), map(转换为任意类型的流)

(3)结束操作:  例如forEach,会返回非流结果,例如基本类型的值(int,float,double)、对象或者集合,或者在终端操作为forEach的情况下没有返回值。

结束操作时才真正进行遍历行为,前面的中间操作也在这个时候真正的执行。

常见的结束操作如下:

forEach()(遍历每个元素),toArray()(转换为数组),min(Comparator)(取最小的元素)

max(Comparator)(取最大的元素),count()(总数),findFirst()(第一个元素)

3.具体用例

首先创建一个100个元素的表,用随机数填充其年龄和ID

  1. Random r = new Random(System.currentTimeMillis());
  2. List<Hero> list = new ArrayList<>();
  3. for (int i = 0; i < 100; i++) {
  4. list.add(new Hero("hero-"+i,r.nextInt(500),r.nextInt(100)));
  5. }

然后执行各种中间操作:

  1. //用filter筛选满足条件的对象,并进行操作
  2. list
  3. .stream()
  4. .filter(h-> h.getId()<300 && h.getAge()>50)
  5. .forEach(h-> System.out.println(h));
  6.  
  7. //用distinct去除重复元素
  8. list
  9. .stream()
  10. .distinct()
  11. .forEach(h-> System.out.print(h));
  12.  
  13. //用sorted进行排序
  14. list
  15. .stream()
  16. .sorted((h1,h2) -> h1.getAge()>h2.getAge() ? 1:-1)
  17. .forEach(h-> System.out.println(h));
  18.  
  19. //用limit保留三个元素
  20. list
  21. .stream()
  22. .limit(3)
  23. .forEach(h-> System.out.println(h));
  24.  
  25. //用skip忽略前三个元素
  26. list
  27. .stream()
  28. .skip(3)
  29. .forEach(h-> System.out.println(h));
  30.  
  31. //用mapToDouble转换为Double的Stream
  32. list
  33. .stream()
  34. .mapToDouble(Hero::getAge)
  35. .forEach(h-> System.out.println(h));
  36.  
  37. //转换为任意类型的Stream
  38. list
  39. .stream()
  40. .map((h)-> h.getName()+"-"+h.getAge()+"-"+h.getId())
  41. .forEach(h-> System.out.println(h));

终端操作(结束操作)的用例如下:

  1. //用forEach遍历集合
  2. list
  3. .stream()
  4. .forEach(h-> System.out.println(h));
  5.  
  6. //用toArray将表变为数组
  7. Object[] arrays = list
  8. .stream()
  9. .toArray();
  10.  
  11. //用min得到最小值
  12. Hero h1 = list
  13. .stream()
  14. .min((hf,hs)->hf.getAge()-hs.getAge())
  15. .get();
  16.  
  17. //用max得到最大值
  18. Hero h2 =list
  19. .stream()
  20. .max((hf,hs) -> hf.getAge()-hs.getAge())
  21. .get();
  22.  
  23. //用count计算流中的数据总数
  24. long count = list
  25. .stream()
  26. .count();
  27.  
  28. //用findFirst得到第一个元素
  29. Hero h3 = list
  30. .stream()
  31. .findFirst()
  32. .get();

测试用例:

  1. Hero h = list
  2. .stream()
  3. .sorted((h1,h2)-> h1.getAge()>h2.getAge() ? -1:1)
  4. .skip(2)
  5. .findFirst()
  6. .get();

Lambda表达式-聚合操作的更多相关文章

  1. Util应用程序框架公共操作类(十二):Lambda表达式公共操作类(三)

    今天在开发一个简单查询时,发现我的Lambda操作类的GetValue方法无法正确获取枚举类型值,以至查询结果错误. 我增加了几个单元测试来捕获错误,代码如下. /// <summary> ...

  2. Util应用程序框架公共操作类(八):Lambda表达式公共操作类(二)

    前面介绍了查询的基础扩展,下面准备给大家介绍一些有用的查询封装手法,比如对日期范围查询,数值范围查询的封装等,为了支持这些功能,需要增强公共操作类. Lambda表达式公共操作类,我在前面已经简单介绍 ...

  3. MybatisPlus Lambda表达式 聚合查询 分组查询 COUNT SUM AVG MIN MAX GroupBy

    一.序言 众所周知,MybatisPlus在处理单表DAO操作时非常的方便.在处理多表连接连接查询也有优雅的解决方案.今天分享MybatisPlus基于Lambda表达式优雅实现聚合分组查询. 由于视 ...

  4. Util应用程序框架公共操作类(七):Lambda表达式公共操作类

    前一篇扩展了两个常用验证方法,本文将封装两个Lambda表达式操作,用来为下一篇的查询扩展服务. Lambda表达式是一种简洁的匿名函数语法,可以用它将方法作为委托参数传递.在Linq中,大量使用La ...

  5. lambda 表达式定制操作

    泛型算法中的定制操作 许多算法都会比较输入序列中的元素以达到排序的效果,通过定制比较操作,可以控制算法按照编程者的意图工作. 普通排序算法: template<class RandomItera ...

  6. Util应用程序框架公共操作类(九):Lambda表达式扩展

    上一篇对Lambda表达式公共操作类进行了一些增强,本篇使用扩展方法对Lambda表达式进行扩展. 修改Util项目的Extensions.Expression.cs文件,代码如下. using Sy ...

  7. λ(lambda)表达式

    理论阶段 函数接口 函数接口是行为的抽象: 函数接口是数据转换器; java.util.Function包.定义了四个最基础的函数接口: Supplier<T>: 数据提供器,可以提供 T ...

  8. java集合框架之聚合操作stream

    参考http://how2j.cn/k/collection/collection-aggregate/702.html#nowhere 聚合操作 JDK8之后,引入了对集合的聚合操作,可以非常容易的 ...

  9. 超强的Lambda Stream流操作

    原文:https://www.cnblogs.com/niumoo/p/11880172.html 在使用 Stream 流操作之前你应该先了解 Lambda 相关知识,如果还不了解,可以参考之前文章 ...

随机推荐

  1. Ubuntu 安装 Docker CE(社区版)

    参考自 https://yeasy.gitbooks.io/docker_practice/install/ubuntu.html#ubuntu-1604- docker-io 是以前早期的版本,版本 ...

  2. D. Concatenated Multiples(离线处理)

    思路:直接离线处理出每个ai 的10倍, 100倍, 1000倍的mod k 后的数值的个数,使用map<int,int >ss[12]存储, ss[x][y]表示 (ai*10x)%k= ...

  3. Oracle 查询表对应的索引

    select col.table_owner "table_owner", idx.table_name "table_name", col.index_own ...

  4. JS正则四个反斜杠的含义

    我们首先来看如下代码,在浏览器中输出的是什么? // 在浏览器中输出的 console.log('\\'); // 输出 \ console.log('\\\\'); // 输出 \\ 一:js正则直 ...

  5. SkylineGlobe7.0.1版本 通过鼠标左右平移模型对象

    帮同事写了一段测试代码,如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "ht ...

  6. 数据标记系列——标记工具Imagtagger

    https://github.com/bit-bots/imagetagger 待有空说一说!

  7. SpringMVC学习手册(一)------工作原理解析

    1.什么是MVC模式 图解:   2.SpringMVC原理图解:       springMVC中的几个组件: 前端控制器(DispatcherServlet):接收请求,响应结果,相当于电脑的CP ...

  8. 三、数据API-3

    预备 返回格式需要包括: // Code 状态码(200,400等) // Msg 提示信息(邮箱格式不正确:数据返回成功等) // Result 返回数据 一.WebAPI与传统MVC的区别是 MV ...

  9. python 条件分支与循环

    一.if判断: 语法一: if 条件: # 条件成立时执行的子代码块 代码1 代码2 代码3 示例: sex='female' age=18 is_beautiful=True if sex == ' ...

  10. jQuery初识之选择器、样式操作和筛选器(模态框和菜单示例)

    一.jQuery 1.介绍 jQuery是一个快速.简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架). jQuery设计的 ...