Java8新特性-Stream

Stream API

Stream 是 数据渠道, 用于操作数据源(集合, 数组等) 所生成的元素序列。

"集合讲的是数据, 流讲的是计算!"

Stream 自己不会存储元素

Stream 不会改变源对象,相反,他们会返回一个持有结果的新Stream

Stream操作是延迟执行的, 这意味着他们会等到需要结果的时候才执行

操作步骤
  1. 创建Stream: 一个数据源 获取一个流

    可以通过Collection 系列集合提供的stream() 串行流 或 parallelStream() 并行流

    可以通过Arrays的静态方法 stream() 获取 数组流

    可以通过Stream类中的静态方法 of()

    创建无限流

  2. 中间操作: 对数据源的数据进行处理 filter() map() 等

  3. 终止操作: 一个终止操作,执行中间操作链,并产生结果

创建Stream

创建 Stream 示例:

 
@Testpublic void test(){//1. 可以通过Collection 系列集合提供的stream() 串行流 或 parallelStream() 并行流List<String> list = new ArrayList<>();Stream<String> s1 = list.stream();​//2.可以通过Arrays的静态方法 stream() 获取 数组流Integer[] s = {2,3,4,5};Stream<Integer> s2 = Arrays.stream(s);​//3.可以通过Stream类中的静态方法 of()Stream<String> ss = Stream.of("abc","123");​//4.创建无限流//迭代Stream<Integer> sss = Stream.iterate(0,x->x+2);​sss.limit(4).forEach(System.out::println);​//生成Stream.generate(()->Math.random()).limit(4).forEach(System.out::println);​}

中间操作

中间操作

多个中间操作可以连起来形成一个流水线, 除非流水线上触发终止操作,否则 中间操作不会执行任何的处理

而在 终止操作时一次性全部处理,成为 "惰性求值"

筛选与切片

filter----- 接收lambda, 从流中排除某些元素

limit(n)------ 截断流, 使其元素不超过给定数量n

skip(n)------- 跳过元素,返回一个扔掉了前n个元素的流, 若流中元素不足n个,则返回一个空流, 与 limit(n) 互补

distinct() --筛选, 通过流所生成元素的hashCode()和equals() 去除 重复元素

虽然代码中没有进行迭代调用,但 Stream API 完成了 内部迭代

中间操作不会执行任何的处理

而在 终止操作时一次性全部处理,成为 "惰性求值"

@Test
public void test(){
List<Emp> emps = Arrays.asList(new Emp("王丽丽",4000,50),new Emp("李四",5000,40),new Emp("王丽丽2",6000,50),new Emp("刘莉莉",7000,60));
// 筛选  薪资大于5000的员工信息
emps.stream()                                 //创建流 .filter(x->x.getSalary()>5000)    //中间操作.forEach(System.out::println);    // 终止操作
}
@Testpublic void test(){List<Emp> emps = Arrays.asList(new Emp("王丽丽",4000,50),new Emp("李四",5000,40),new Emp("王丽丽2",6000,50),new Emp("刘莉莉",7000,60));// 筛选  薪资大于5000的员工信息emps.stream().filter(x->x.getSalary()>4000).limit(2).forEach(System.out::println);}
如果 filter 筛选后 有 5 条 符合条件的, 那么 limit(2) 就是取 前2条那么 skip(2) 就是 跳过前2条 ,往后取2条distnict() 	去重 要注意 实体类 重写 hashCode与equals 方法
映射

map()---- 接收 Lambda ,将 元素转换成其他形式提取信息, 接收一个函数作为参数, 该函数会被应用到每个元素上,并将其映射成一个新的元素

flatMap--- 接收一个函数作为参数, 将 流中的每个值 都换成另一个流, 然后把所有流连续成一个流

提取员工姓名:

 @Testpublic void test(){List<Emp> emps = Arrays.asList(new Emp("王丽丽",4000,50),new Emp("李四",5000,40),new Emp("王丽丽2",6000,50),new Emp("刘莉莉",7000,60));// 提取员工姓名emps.stream().map(e->e.getName())    // 或 .map(Emp::getName).forEach(System.out::println);}​
​map 与flatMap 关系 类似于 List 接口中 add() 与addAll()​在测试类中 编写如下代码 :
List<String> list1  =Arrays.asList("aaa","bbbb","ccc");List list2 = new ArrayList();list2.add(2222);list2.add(111);list2.add(list1);System.out.println(list2);
 //此时  list2 为 [2222, 111, [aaa, bbbb, ccc]]    , 长度为 3​在测试类 执行以下代码:
  List<String> list1  =Arrays.asList("aaa","bbbb","ccc");List list2 = new ArrayList();list2.add(2222);list2.add(111);list2.addAll(list1);System.out.println(list2);System.out.println(list2.size());
 ​//此时  list2 为 [2222, 111, aaa, bbbb, ccc] , 长度 为 5 , ​  ​
排序

sorted()----- 自然排序 --使用 Comparable

sorted(Comparator com)----- 定制排序-- 使用 Comparator

@Testpublic void test(){List<Emp> emps = Arrays.asList(new Emp("王丽丽",4000,50),new Emp("李四",5000,40),new Emp("王丽丽2",6000,50),new Emp("刘莉莉",7000,60));// 提取员工薪资 并 升序 排列emps.stream().map(Emp::getSalary).sorted().forEach(System.out::println);​}​​// 定制排序 ,按照 年龄排 ,年龄相同 按照 姓名排, @Testpublic void test(){List<Emp> emps = Arrays.asList(new Emp("王丽丽",4000,50),new Emp("李四",5000,40),new Emp("王丽丽2",6000,50),new Emp("刘莉莉",7000,60));// 提取员工姓名emps.stream().sorted((e1,e2)->{if(e1.getAge() == e2.getAge()){return e1.getName().compareTo(e2.getName());}else{return Integer.compare(e1.getAge(),e2.getAge()); // 升序, 可以返回负的 就是降序}}).forEach(System.out::println);​}​
终止操作

终端操作 会从 流的流水线 生成结果, 其结果可以是任何不是流的值

查找与匹配

allMatch------ 检查是否匹配所有元素 ,返回值为 boolean

anyMatch-----检查是否至少匹配一个元素 返回值为 boolean

noneMatch---- 检查是否没有匹配所有元素 返回值为 boolean

findFirst---- 返回第一个元素, 返回Optional 对象, 可以通过get() 获得首个元素

findAny----- 返回当前流中的任意元素,返回Optional 对象, 可以通过get() 获得首个元素

count-----返回流中元素的总个数 , 返回long

max------ 返回流中最大值

min------返回流中最小值

forEach--- 内部迭代

 //为 Emp.java 增加枚举类型 Status@NoArgsConstructor@AllArgsConstructor@Data@ToStringpublic class Emp {private String name;private double salary;private int age;private Status status;  //枚举类型​//  空闲, 忙碌 ,休假public enum Status {FREE,BUSY,VOCATION   }}​//测试类@Testpublic void test(){List<Emp> emps = Arrays.asList(new Emp("王丽丽",4000,50, Emp.Status.FREE),new Emp("李四",5000,40, Emp.Status.FREE),new Emp("王丽丽2",6000,50,Emp.Status.FREE),new Emp("刘莉莉",7000,60,Emp.Status.FREE));//检测 员工是否都属于 BUSY 状态boolean b = emps.stream().noneMatch(e -> e.getStatus().equals(Emp.Status.FREE));​System.out.println(b);// 取 工资最高的 员工信息Optional<Emp> first = emps.stream().sorted((e1, e2) -> -Double.compare(e1.getSalary(), e2.getSalary())).findFirst();System.out.println(first.get());  //获得 员工的相关信息​// stream() 串行流, parallelStream() 并行流Optional<Emp> first = emps.parallelStream().filter(e->e.getStatus().equals(Emp.Status.BUSY)).findAny();System.out.println(first.get());// 取 工资最高(最低)的 员工信息Optional<Emp> max = emps.stream()​.max((e1,e2)->Double.compare(e1.getSalary(),e2.getSalary()));// 改为min​System.out.println(max.get());}​​
归约与收集

归约:

reduce(T t,BinaryOpeartor op) 或 reduce(BinaryOpeartor op) --可以将流中的元素 反复 结合起来, 得到一个值

 @Testpublic void test(){​List<Integer> nums= Arrays.asList(1,2,3,4,5,6,7,8,9,10);// 对集合里的数 进行累加求和Integer reduce = nums.stream().reduce(0, (x, y) -> x + y); // 0 是 初始值, 第二个参数 要执行累加操作System.out.println("sum="+reduce);  //55​​// 计算当前 所有员工的 薪资总和List<Emp> emps = Arrays.asList(new Emp("王丽丽",4000,50, Emp.Status.BUSY),new Emp("李四",5000,40, Emp.Status.FREE),new Emp("王丽丽2",6000,50,Emp.Status.BUSY),new Emp("王丽丽3",9000,50,Emp.Status.BUSY),new Emp("王丽丽4",1000,50,Emp.Status.BUSY)​);//  有 初值0.0 返回 DoubleDouble reduce1 = emps.stream().map(e -> e.getSalary())    //提取薪资.reduce(0.0, (e1, e2) -> e1 + e2); //薪资求和  Double::sum 也可以System.out.println(reduce1);​​// 没有初值 返回 Optional 对象Optional<Double> reduce2 = emps.stream().map(e -> e.getSalary())    //提取薪资.reduce(Double::sum);  // 没有初值, 返回Optional​System.out.println(reduce2.get());}
要 注意 reduce 有没有初值时 ,返回值 不同 

收集

collect--- 将 流 转换为其他形式, 接收一个Collector接口的实现, 用于给 Stream中元素汇总的方法

Collector 接口中 方法的实现 决定了 如何对流执行 收集操作 (如 收集到 List Set Map)

Collectors 实现类提供了 很多静态方法, 可以方便地创建常见收集器实例

示例:

 @Testpublic void test(){​List<Emp> emps = Arrays.asList(new Emp("王丽丽",4000,50, Emp.Status.BUSY),new Emp("李四",5000,40, Emp.Status.FREE),new Emp("王丽丽2",6000,50,Emp.Status.BUSY),new Emp("王丽丽3",9000,50,Emp.Status.BUSY),new Emp("王丽丽4",1000,50,Emp.Status.BUSY)​);// 收集 所有员工的姓名,并放到集合中去List<String> collect = emps.stream().map(Emp::getName).collect(Collectors.toList());collect.forEach(System.out::println);​// 总工资的平均值   averagingDouble 平均值, summingDouble 求和,maxBy 最大, minBy 最小Double avg = emps.stream().collect(Collectors.averagingDouble(Emp::getSalary));System.out.println(avg);​// 分组, 计算 每个状态的 薪资总和Map<Emp.Status, List<Emp>> group = emps.stream().collect(Collectors.groupingBy(Emp::getStatus));System.out.println(group);​// 分区, 满足条件一个区, 不满足条件的一个区// 薪资大于等于6000 为一区, 小于为 另一区Map<Boolean, List<Emp>> collect = emps.stream().collect(Collectors.partitioningBy(e -> e.getSalary() >= 6000));System.out.println(collect);​// 提取姓名, 并用 逗号 分隔, 首尾的逗号 均已去除String str = emps.stream().map(Emp::getName).collect(Collectors.joining(","));System.out.println(str);}​

Stream Api 练习题

给定一个数字列表, 如何返回一个由每个数的平方构成的列表呢?

给定[1,2,3,4,5], 应该返回[1,4,9,16,25]

 @Testpublic void test4(){List<Integer> list = Arrays.asList(1,2,3,4,5);list.stream().map(e->e*e).forEach(System.out::println);}

怎样用 map 和reduce 方法 数一数 流中 有多少个Emp呢?

 @Testpublic void test4(){List<Emp> emps = Arrays.asList(new Emp("王丽丽",4000,50, Emp.Status.BUSY),new Emp("李四",5000,40, Emp.Status.FREE),new Emp("王丽丽22",8000,50,Emp.Status.VOCATION),new Emp("王丽丽4",1000,50,Emp.Status.VOCATION)​);​Integer reduce = emps.stream().map(e -> 1).reduce(0, (e1, e2) -> e1 + e2);  //.reduce(0,Integer::sum);System.out.println(reduce);}

 //交易员类@AllArgsConstructor@NoArgsConstructor@Data@ToStringpublic class Trader {private String name;private String city;}
 //交易类@AllArgsConstructor@NoArgsConstructor@Data@ToStringpublic class Transaction {private Trader trader;private int year;private int value;​}
 // 交易测试类public class TestTrans {​List<Transaction> transactions = null;​@Beforepublic void before(){Trader t1 = new Trader("t1","tj");Trader t2 = new Trader("t2","sh");Trader t3 = new Trader("t3","tj");Trader t4 = new Trader("t4","tj");​transactions = Arrays.asList(new Transaction(t4,2011,300),new Transaction(t1,2012,1000),new Transaction(t1,2011,400),new Transaction(t2,2012,710),new Transaction(t2,2012,700),new Transaction(t3,2012,950));}}

根据以上内容 编写测试类, 完成以下练习题

 @Testpublic void test(){//找出2011年发生的所有交易, 并按交易额排序, (从低到高)transactions.stream().filter(x->x.getYear()==2011).sorted((x1,x2)->Integer.compare(x1.getValue(),x2.getValue())).forEach(System.out::println);//交易员都在哪些不同的城市工作过,transactions.stream().map(e->e.getTrader().getCity()).distinct().forEach(System.out::println);//查找所有来自 tj的交易员,并按姓名排序System.out.println("---------------3---------");transactions.stream().filter(x->x.getTrader().getCity().equals("tj")).map(x->x.getTrader().getName()).distinct().sorted((x1,x2)->x1.compareTo(x2)).forEach(System.out::println);//返回所有交易员的姓名字符串,按字母顺序排序System.out.println("---------------4---------");transactions.stream().map(x->x.getTrader().getName()).distinct().sorted((x1,x2)->x1.compareTo(x2)).forEach(System.out::println);//有没有交易员是在sh工作的?boolean sh = transactions.stream().anyMatch(x -> x.getTrader().getCity().equals("sh"));System.out.println("------="+sh);//打印生活在tj的交易员的所有交易额System.out.println("---6---");Integer sum = transactions.stream().filter(x -> x.getTrader().getCity().equals("tj")).map(x -> x.getValue()).reduce(0, (x1, x2) -> x1 + x2);System.out.println(sum);​//所有交易中, 最高的交易额是多少Optional<Integer> max = transactions.stream().map(x -> x.getValue()).max(Integer::compare);System.out.println("-------"+max.get());//找到交易额最小的交易Optional<Integer> min = transactions.stream().map(x -> x.getValue()).min(Integer::compare);System.out.println("-------"+min.get());}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/622406.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

49 C++ 多个线程之间共享资源问题。lock , unlock

前提&#xff0c;我们要补充一个知识点。再使用类成员函数做为 线程启动的入口&#xff0c;第二个参数可以传递对象 和 对象地址&#xff0c;如下&#xff1a; 类似这样&#xff1a;thread readthread(&Teacher164::readfunc,tea);thread readthread(&Teacher164::read…

C# 基础入门

第二章 C# 语法基础 2-1 C# 中的关键字 关键字&#xff0c;是一些被C#规定了用途的重要单词。 在Visual Studio的开发环境中&#xff0c;关键字被标识为蓝色&#xff0c;下图代码中&#xff0c;用红方框圈出的单词就是关键字。 关键字 class &#xff0c;这个关键字的用途是…

Linux下编写zlg7290驱动(1)

大家好&#xff0c;今天给大家介绍Linux下编写zlg7290驱动(1)&#xff0c;文章末尾附有分享大家一个资料包&#xff0c;差不多150多G。里面学习内容、面经、项目都比较新也比较全&#xff01;可进群免费领取。 在智能仪表中&#xff0c;经常会用到键盘、数码管等外设。因此&…

一个div内有好几个p元素,如何清空 / 删除 p元素的数据

一个div内有好几个p元素&#xff0c;如何清空p元素的数据 若要清空一个 div 内多个 p 元素的数据&#xff0c;可以遍历该 div 中的所有 p 元素&#xff0c;并设置它们的 textContent 或 innerHTML 属性为空字符串&#xff0c;这样即可清空它们的内容。 以下是一个示例&#x…

Redis学习指南(5)-Redis-Desktop的安装

前言 Redis-Desktop是一款开源的Redis图形化管理工具&#xff0c;它提供了直观的用户界面&#xff0c;方便用户对Redis数据库进行可视化管理。本文将介绍Redis-Desktop的安装步骤以及基本的使用方式。 安装 Redis-Desktop Redis-Desktop支持多个平台&#xff0c;包括Windows…

【Java语言基础②】Java基本语法——Java程序基本格式,注释,标识符,常量

通过前面的学习&#xff0c;大家对Java语言有了一个基础认识&#xff0c;但现在还无法使用Java语言编写程序&#xff0c;要熟练使用Java语言编写程序&#xff0c;必须充分掌握Java语言的基础知识。今天咱们就来聊一聊Java的基本语法。 1.java程序的基本格式 Java程序代码必须…

Spring Boot 3 + Vue 3实战:引入数据库实现用户登录功能

文章目录 一、实战概述二、实战步骤&#xff08;一&#xff09;创建数据库&#xff08;二&#xff09;创建用户表&#xff08;三&#xff09;后端项目引入数据库1、添加相关依赖2、用户实体类保持不变3、编写应用配置文件4、创建用户映射器接口5、创建用户服务类6、修改登录控制…

剑指offer题解合集——Week3day6

文章目录 剑指offerWeek3周六&#xff1a;栈的压入、弹出序列AC代码思路&#xff1a; 周六&#xff1a;不分行从上往下打印二叉树AC代码思路&#xff1a; 剑指offerWeek3 周六&#xff1a;栈的压入、弹出序列 题目链接&#xff1a;栈的压入、弹出序列 输入两个整数序列&…

element plus自定义组件表单校验

方式一&#xff1a; import { formContextKey, formItemContextKey } from "element-plus";// 获取 el-form 组件上下文 const formContext inject(formContextKey, void 0); // 获取 el-form-item 组件上下文 const formItemContext inject(formItemContextKey, …

NLP论文阅读记录 - 2021 | WOS 使用深度强化学习及其他技术进行自动文本摘要

文章目录 前言0、论文摘要一、Introduction1.1目标问题1.2相关的尝试1.3本文贡献 二.相关工作2.1. Seq2seq 模型2.2.强化学习和序列生成2.3.自动文本摘要 三.本文方法四 实验效果4.1数据集4.2 对比模型4.3实施细节4.4评估指标4.5 实验结果4.6 细粒度分析 五 总结思考 前言 Auto…

Java:常见算法

认识算法 什么是算法&#xff1f; 解决某个实际问题的过程和方法 学习算法的技巧 先搞清楚算法的流程直接去推敲如何写代码 排序算法 冒泡排序 每次从数组中找出最大值放在数组的后面去。 实现冒泡排序的关键步骤分析 确认总共需要做几轮&#xff1a;数组的长度-1每轮比较…

【java】创建打印数组的方法并调用

java的数组和Python不一样&#xff0c;不能直接用print打印&#xff0c;而如果每次都用循环的方法&#xff0c;比较麻烦&#xff0c;就直接创建一个类&方法&#xff0c;每次用的时候直接调用。 public class list_deal {public static void printArray(int[] arr){for (in…

Python实现对角但非同一性协方差结构回归模型(WLS算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 WLS回归分析是一种常用的回归分析方法&#xff0c;通过对数据进行加权处理&#xff0c;可以更准确地评…

构造函数的初始化列表

一、什么是初始化列表 初始化列表&#xff1a;以一个冒号开始&#xff0c;接着是一个以逗号分隔的数据成员列表&#xff0c;每个"成员变量"后面跟 一个放在括号中的初始值或表达式。 class Date { public:Date(int year, int month, int day): _year(year), _month(m…

VSCode编写 C/C++ 程序

VSCode 全称 Visual Studio Code&#xff0c;是微软出的一款轻量级代码编辑器&#xff0c;免费、开源而且功能强大。它支持几乎所有主流的程序语言的语法高亮、智能代码补全、自定义热键、括号匹配、代码片段、代码对比 Diff、GIT 等特性&#xff0c;支持插件扩展&#xff0c;并…

Day02

今日任务&#xff1a; 977 有序数组的平方209 长度最小的子数组59 螺旋矩阵Ⅱ 977 有序数组的平方 题目链接&#xff1a;https://leetcode.cn/problems/squares-of-a-sorted-array/ 双指针问题&#xff0c;以及数组本身时有序的&#xff1b; 思路&#xff1a; 左、右两个…

SG-8101CGA 系列 (晶体振荡器 可编程 可用 +125°C )

SG-8101CGA是可编程晶体振荡器&#xff0c;具有CMOS输出&#xff0c;适用于汽车&#xff0c;同时&#xff0c;该系列还提供相同的频率和其他参数的轻松编程能力&#xff0c;符合AEC-Q100标准&#xff0c;具有出色的电磁兼容性和稳定性&#xff0c;可以在各种环境下使用。外部尺…

Linux的DHCP工作原理和dns服务器

目录 一、DHCP原理 1.DHCP的好处 2.DHCP的分配方式 3.实验 二、dns服务器 1.什么是dns 2.dns域名解析 3、在内网搭建dns 一、DHCP原理 DCHP工作原理使用C/S架构 &#xff08;1&#xff09;第一步&#xff0c;客户端广播发送一个discover报文寻找DHCP服务器。 &#…

cf919Div2C题题目总结

Problem - C - Codeforces 这道题其实是一道数学题。 先看第一个变量&#xff0c;也就是我们要求的答案k的数量&#xff0c;但看k是很好确定它的限制条件的&#xff0c;要想均匀分成k份&#xff0c;n%k必须为0&#xff0c;有了k&#xff0c;我们再来看m&#xff0c;对于a(1)和…