java8新特性——StreamAPI

说明:

java8中有两大最为重要的改变。第一个是Lambda表达式;另外一个则是Stream API。

Stream API(java.util.stream)把真正的函数式编程风格引入java。这是目前为止对java类库最好的补充,因为Stream API可以极大提供java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

Stream是java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API对集合数据进行操作,就类似于使用sql执行的数据库查询。也可以使用Stream API并执行操作。简言之,Stream API提供了一种高效且易于使用的处理数据的方式

 为什么使用Stream API?

实际开发中,项目中多数数据源来自于Mysql、Oracle等。但现在数据源可以更多了,有mondb,redis等,而这些NoSql的数据就需要jaav层面去处理。

 什么是Stream?

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

 Stream和Collection集合区别?

1.Collection是一种静态的内存数据结构,讲的是数据,而Stream是有关计算的,讲的是计算。前者是主要面向内存,存储在内存中,后者主要是面向CPU,通过CPU实现计算。

2.Stream API关注的是多个数据的计算(排序、查找、过滤、映射、遍历等)

3.集合关注的是数据的存储,面向内存的

 使用说明?

1.Stream自己不会存储元素。(针对数据计算)

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

3.Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。即一旦执行终止操作,就执行中间操作链,并产生结果。

4.Stream一旦执行了终止操作,就不能再调用其它中间操作或终终止操作了~

 操作步骤

  1. Stream的实例化
  2. 一系列的中间操作
  3. 执行终止操作

数据准备:

创建Employee类

package data;
import com.oracle.webservices.internal.api.databinding.DatabindingMode;
public class Employee {private long id;private String name;private int age;private double salary;public Employee(long id,String name,int age,double salary){this.id = id;this.age = age;this.name = name;this.salary = salary;}public long getId() {return id;}public void setId(long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public double getSalary() {return salary;}public void setSalary(double salary) {this.salary = salary;}@Overridepublic String toString(){return "Employee{"+"id="+id+",name="+name+",age="+age+",salary="+salary+"}";}}

创建EmployeeData类

package data;import java.util.ArrayList;
import java.util.List;public class EmployeeData {public static List<Employee> getEmployees(){List<Employee> list = new ArrayList<>();list.add(new Employee(1001,"马化腾",34,6000.38));list.add(new Employee(1002,"马云",2,9876.38));list.add(new Employee(1003,"刘强东",33,3000.82));list.add(new Employee(1004,"雷军",26,7657.37));list.add(new Employee(1005,"李彦宏",65,5555.38));list.add(new Employee(1006,"比尔盖茨",42,9500.38));list.add(new Employee(1007,"任正非",34,4333.32));list.add(new Employee(1008,"扎克伯格",35,2500.32));return list;}
}

1.创建Stream(三种方式)

package streamTest;import data.Employee;
import data.EmployeeData;
import org.junit.jupiter.api.Test;import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;public class StreamAPITest {//创建Stream方式一:通过集合@Testpublic  void test1(){List<Employee> list = EmployeeData.getEmployees();//返回一个shuixuStream<Employee> stream = list.stream();//返回一个并行流Stream<Employee> stream1 = list.parallelStream();}//创建Stream方式二:通过数组@Testpublic void test2(){//调用Arrays类的static<T> Stream<T> stream(T[] array):返回一个流Integer[] arr = new Integer[]{1,2,3,4,5};Stream<Integer> stream = Arrays.stream(arr);int[] arr1 = new int[]{1,2,3,4,5,6,7};IntStream stream1 = Arrays.stream(arr1);}//创建Stream方式大三:通过Stream的of()@Testpublic void text3(){Stream<String> stream = Stream.of("AA", "BB", "C");}
}

 2.一系列的在中间操作

1.筛选与切片

2.映射

 3.排序

1.筛选与切片

package streamTest;import data.Employee;
import data.EmployeeData;
import org.junit.jupiter.api.Test;import java.util.List;
import java.util.stream.Stream;public class StreamAPITest1 {//1-筛选与切片@Testpublic void test(){//filter(Predicate p)——接收Lambda,从流中排除某些元素//查询员工表中薪资大于7000的员工信息List<Employee> list = EmployeeData.getEmployees();System.out.println(list);Stream<Employee> stream = list.stream();stream.filter(emp -> emp.getSalary() > 7000).forEach(System.out::println);System.out.println();//limit(n)——截断流,使其元素不超过给定数量//错误的。因为stream已经执行了终止操作,就不可以在调用其他的中间操作或终止操作了// stream.limit(2).forEach(System.out::println);list.stream().filter(emp -> emp.getSalary()>7000).limit(2).forEach(System.out::println);// skip(n) ——跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,返回一个空流。list.stream().skip(5).forEach(System.out::println);}
}

注意:如果stream已经执行了终止操作,不可以在调用其他的中间操作或终止操作 

2.映射

//2-映射@Testpublic void test2() {//map(Function f)——接收一个函数作为参数,将元素转换成其他形式或提取信息,该函数会被映射到每个元素上//转换为大写List<String> list = Arrays.asList("aa", "bb", "cc", "dd");//方式一:list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);//方式二:list.stream().map(String::toUpperCase).forEach(System.out::println);//获取员工姓名长度大于3的员工List<Employee> employees = EmployeeData.getEmployees();employees.stream().filter(employee -> employee.getName().length()>3).forEach(System.out::println);//获取员工姓名长度大于3的员工的姓名employees.stream().filter(employee -> employee.getName().length()>3).map(employee -> employee.getName()).forEach(System.out::println);}

3.排序

//3-排序@Testpublic void test3(){//sorted()——自然排序Integer[] arr = new Integer[]{ 342,3,64,46,7,3,54,65,68};String[] arr1 = new String[]{"GG","DD","MM","SS","JJ"};Arrays.stream(arr).sorted().forEach(System.out::println);//arr数组并没有因为升序做调整Arrays.stream(arr1).sorted().forEach(System.out::println);//arr数组并没有因为升序做调整//因为Employee没有实现Comparable接口,所以报错!
//        List<Employee> list = EmployeeData.getEmployees();
//        list.stream().sorted().forEach(System.out::println);//sorted(Comparator com)——定制排序List<Employee> list = EmployeeData.getEmployees();//升序list.stream().sorted((e1,e2)-> e1.getAge()- e2.getAge()).forEach(System.out::println);System.out.println();//降序list.stream().sorted((e1,e2)-> e2.getAge()- e1.getAge()).forEach(System.out::println);//针对字符串从大到小Arrays.stream(arr1).sorted((s1,s2)->s2.compareTo(s1)).forEach(System.out::println);}

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

3.终止操作

package streamTest;import data.Employee;
import data.EmployeeData;
import org.junit.jupiter.api.Test;import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;/*** 终止操作*/
public class StreamAPITest2 {//1-匹配与查找@Testpublic void test(){//是否所有的员工的年龄都大于18//allMatch(Predicate p)——检查是否匹配所有元素List<Employee> list = EmployeeData.getEmployees();System.out.println(list.stream().allMatch(emp -> emp.getAge() > 18 ));//是否存在年龄大于18岁的员工//anyMatch(Predicate p)——检查是否至少匹配一个元素System.out.println(list.stream().anyMatch(emp -> emp.getAge() > 18));//是否存在员工的工资大于10000System.out.println(list.stream().anyMatch(emp -> emp.getSalary() > 10000));//findFirst——返回第一个元素System.out.println(list.stream().findFirst().get());}@Testpublic void test2(){List<Employee> list = EmployeeData.getEmployees();System.out.println(list.stream().filter(employee -> employee.getSalary()>7000).count());//max(Comparator c)——返回流中的最大值//返回最高工资的员工System.out.println(list.stream().max((e1,e2)->Double.compare(e1.getSalary(), e2.getSalary())));//返回最低的工资//方式一:System.out.println(list.stream().max((e1,e2)->Double.compare(e1.getSalary(), e2.getSalary())).get().getSalary());//方式二:System.out.println(list.stream().map(employee -> employee.getSalary()).max((e1,e2)->Double.compare(e1, e2)).get());//min(Comparator c)——返回流中的最小值//返回最低工资的员工System.out.println(list.stream().min((e1,e2)->Double.compare(e1.getSalary(), e2.getSalary())));//forEach(Consumer c)——内部迭代list.stream().forEach(System.out::println);//针对于集合,jdk8中增加了一个遍历的方法list.forEach(System.out::println);}//归约@Testpublic void test3(){//reduce(T identity,BinaryOperator)——可以将流中元素反复结合起来,得到一个值。返回T//计算1-10的自然数的和List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);System.out.println(list.stream().reduce(0,(x1,x2)->x1+x2));System.out.println(list.stream().reduce(10,(x1,x2)->x1+x2));//reduce(BinaryOperator)——可以将流中元素反复结合起来,得到一个值。返回Optional<T>//计算公司所有员工工资的和List<Employee> employeeList = EmployeeData.getEmployees();System.out.println(employeeList.stream().map(emp -> emp.getSalary()).reduce((salary1, salary2) -> Double.sum(salary1, salary2)));}@Testpublic void test4(){//collect(Collector c)——将流转换为其他形式。接受一个Collector接口的实现,用于给Stream中的元素做汇总的方法//查找工资大于6000的员工,结果返回为一List或SetList<Employee> list = EmployeeData.getEmployees();List<Employee> list1 = list.stream().filter(emp -> emp.getSalary() > 6000).collect(Collectors.toList());list1.forEach(System.out::println);//按照员工的年龄进行排序,返回到一个新的List中System.out.println();List<Employee> list2 = list.stream().sorted((e1, e2) -> e1.getAge() - e2.getAge()).collect(Collectors.toList());list2.forEach(System.out::println);}
}

 总结

1.程序运行中,流Stream只能使用一次,使用后会默认关闭,不能重复使用;重复使用会报错,信息如下:

Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closedat java.util.stream.AbstractPipeline.spliterator(AbstractPipeline.java:343)at java.util.stream.Stream.concat(Stream.java:1080)



2.在开发过程中,建议使用Stream.of(list),解决list为null的问题;使用list.stream()之前需要判断list是否为null,避免报错空指针异常(java.lang.NullPointerException)。
3.stream流遍历获取的对象是原对象
4.stream特性思维导图:

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

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

相关文章

AI:130-基于深度学习的室内导航与定位

🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带有在本地跑过的关键代码,详细讲解供…

红蓝对抗:网络安全领域的模拟实战演练

引言&#xff1a; 随着信息技术的快速发展&#xff0c;网络安全问题日益突出。为了应对这一挑战&#xff0c;企业和组织需要不断提升自身的安全防护能力。红蓝对抗作为一种模拟实战演练方法&#xff0c;在网络安全领域得到了广泛应用。本文将介绍红蓝对抗的概念、目的、过程和…

硬盘合并分区失败显示未格式化怎么办?看这里

在当今数字化时代&#xff0c;硬盘分区已成为计算机存储管理的重要手段。然而&#xff0c;在使用过程中&#xff0c;我们有时会遇到“合并分区失败显示未格式化”的问题&#xff0c;这不仅影响了我们的工作效率&#xff0c;还可能造成数据丢失的风险。下面将根据不同情况给予不…

【LeetCode: 107. 二叉树的层序遍历 II + BFS】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

node+vue3+mysql前后分离开发范式——实现视频文件上传并渲染

文章目录 ⭐前言⭐ 功能设计与实现💖 node上传文件写入file_map映射表💖 vue3前端上传文件回显⭐ 效果⭐结束⭐前言 大家好,我是yma16,本文分享关于 node+vue3+mysql前后分离开发范式——实现视频文件上传并渲染。 技术选型 前端:vite+vue3+antd 后端:node koa 数据库…

JVM-垃圾回收(标记算法,收集器)

申明&#xff1a;文章内容是本人学习极客时间课程所写&#xff0c;文字和图片基本来源于课程资料&#xff0c;在某些地方会插入一点自己的理解&#xff0c;未用于商业用途&#xff0c;侵删。 原资料地址&#xff1a;课程资料 垃圾回收的基本原理 1 什么是垃圾&#xff1f; 在…

阿里云ECS香港服务器性能强大_安全可靠香港免备案服务器

阿里云香港服务器中国香港数据中心网络线路类型BGP多线精品&#xff0c;中国电信CN2高速网络高质量、大规格BGP带宽&#xff0c;运营商精品公网直连中国内地&#xff0c;时延更低&#xff0c;优化海外回中国内地流量的公网线路&#xff0c;可以提高国际业务访问质量。阿里云服务…

视觉slam十四讲学习笔记(六)视觉里程计 1

本文关注基于特征点方式的视觉里程计算法。将介绍什么是特征点&#xff0c;如何提取和匹配特征点&#xff0c;以及如何根据配对的特征点估计相机运动。 目录 前言 一、特征点法 1 特征点 2 ORB 特征 FAST 关键点 BRIEF 描述子 3 特征匹配 二、实践&#xff1a;特征提取…

《Linux 简易速速上手小册》第2章: 命令行的艺术(2024 最新版)

文章目录 2.1 基本 Linux 命令2.1.1 重点基础知识2.1.2 重点案例&#xff1a;整理下载文件夹2.1.3 拓展案例 1&#xff1a;批量重命名文件2.1.4 拓展案例 2&#xff1a;查找并删除特定文件 2.2 文件和目录管理2.2.1 重点基础知识2.2.2 重点案例&#xff1a;部署一个简单的网站2…

SpringMVC速成(二)

文章目录 SpringMVC速成&#xff08;二&#xff09;1.SSM整合1.1 流程分析1.2 整合配置步骤1&#xff1a;创建Maven的web项目步骤2:添加依赖步骤3:创建项目包结构步骤4:创建SpringConfig配置类步骤5:创建JdbcConfig配置类步骤6:创建MybatisConfig配置类步骤7:创建jdbc.properti…

《Go 简易速速上手小册》第2章:控制结构与函数(2024 最新版)

文章目录 2.1 条件语句&#xff1a;决策的艺术2.1.1 基础知识讲解2.1.2 重点案例&#xff1a;用户角色权限判断实现用户角色权限判断扩展功能实现代码功能扩展&#xff1a;添加或删除用户 2.1.3 拓展案例 1&#xff1a;成绩等级判断实现成绩等级判断功能实现代码扩展功能&#…

Electron实战之进程间通信

进程间通信&#xff08;IPC&#xff09;并非仅限于 Electron&#xff0c;而是源自甚至早于 Unix 诞生的概念。尽管“进程间通信”这个术语的确创造于何时并不清楚&#xff0c;但将数据传递给另一个程序或进程的理念可以追溯至 1964 年&#xff0c;当时 Douglas McIlroy 在 Unix…

Windows 连接共享文件夹 切换/退出账号操作

工作中遇到个问题&#xff0c;登录公司内部共享文件夹&#xff0c;使用自己的账号&#xff0c;但需要切换别人账号找东西时&#xff0c;没有发现登出的地方。在网上找了两种方法&#xff1a;通过命令行登出账号的方法 &#xff08;1&#xff09;打开cmd命令提示符&#xff0c;…

对待不合理需求,前端工程师如何优雅的say no!

曾经有位老板&#xff0c; 每次给前端提需求&#xff0c;前端都说实现不了&#xff0c;后来他搜索了一下&#xff0c;发现网上都有答案。他就在招聘要求上加了条&#xff1a;麻烦你在说不行的时候&#xff0c;搜索一下。 上面是一个段子&#xff0c;说的有点极端了&#xff0c;…

Java集合篇之深入解析ArrayList,这六问你答的上来吗?

写在开头 开年第一篇&#xff0c;先祝各位新的一年身体健康&#xff0c;学业有成&#xff0c;事业有成哈&#xff0c;春节期间就是咔咔乱吃&#xff0c;咔咔乱玩&#xff0c;把学习都抛一边子去了&#xff0c;已经9天没有学习了&#xff0c;深深的懊悔&#xff0c;从今天开始&…

Leetcode1423.可获得的最大点数

文章目录 题目原题链接思路&#xff08;逆向思维&#xff09; 题目 原题链接 Leetcode1423.可获得的最大点数 思路&#xff08;逆向思维&#xff09; 由题目可知&#xff0c;从两侧选k张&#xff0c;总数为n张&#xff0c;即从中间选n - k张 nums总和固定&#xff0c;要选k张最…

[CTF]-PWN:C++文件更换libc方法(WSL)

C文件与C文件更换libc有很多不一样的地方&#xff0c;我是在写buu的ciscn_2019_final_3才意识到这个问题&#xff0c;C文件只需要更换libc和ld就可以了&#xff0c;但是C文件不同&#xff0c;除了更换libc和ld&#xff0c;它还需要更换libstdc.so.6和libgcc_s.so.1 更换libc和…

[SWPUCTF 2021 新生赛]crypto8

第一眼看见是乱码不确定是什么的编码 看了下感觉是UUencode编码 UUencode编码是一种古老的编码方式&#xff0c;通常用于将二进制数据转换成可打印字符的形式。UUencode编码采用一种基于64个字符的编码表&#xff0c;将每3个字节的数据编码为4个可打印字符&#xff0c;以实现…

vue导出word文档(图文示例)

第076个 查看专栏目录: VUE 本文章目录 示例说明示例效果图导出的文件效果截图示例源代码参数说明&#xff1a;重要提示&#xff1a;API 参考网址 示例说明 在Vue中导出Word文档&#xff0c;可以使用第三方库file-saver和html-docx-js。首先需要安装这两个库&#xff1a; npm …

库的操作【数据库】

目录 一、创建数据库 二、删除数据库 ​编辑 三、数据库编码问题 四、库的改查 查 1&#xff09;查有哪些数据库&#xff1a; 2&#xff09;使用某个数据库&#xff1a; 3&#xff09;当前在哪个数据库&#xff1a; 4&#xff09;有谁在使用 改alter 五、备份和恢复 …