java8 Lambda表达式以及Stream 流

Lambda表达式
Lambda表达式规则
  • Lambda表达式可以看作是一段可以传递的代码,

  • Lambda表达式只能用于函数式接口,而函数式接口只有一个抽象方法,所以可以省略方法名,参数类型等

  • Lambda格式:(形参列表) -> Lambda体 ; 在java中Lambda表达式本质是函数式接口的实现

     Runnable runnable = () -> System.out.println("执行任务") ;
    
    • 形参列表是接口中的抽象方法的形参列表
    • Lambda体 是重写的抽象方法的方法体
  • Lambda语法:

    • 形参列表 中 参数类型可以省略,如果只有一个参数,小括号可以省略
    • lambda体如果只有一行语句,return和 {} 都可以省略

java常见的函数式接口,可以根据自己的业务需求重新这些方法简化代码

  • Consumer,消费型接口,有参数无返回,对参数进行某种操作

    void accept(T t);
    
  • Supplier,供给型接口,无参有返回,返回某个对象

    T get();
    
  • Function,函数型接口,有参有返回,对 T类型的参数进行操作返回 R类型的结果

    R apply(T t);private static void extracted() {//  Function<T, R> T为入参,R为返回结果Function<Integer,String> function = (in)->{return in+"123";};String apply = function.apply(12);System.out.println(apply); //12123}
    
  • Predicate,断定型接口,有参有返回,输入参数T,返回boolean值,用于判断对象是否满足某个条件

    boolean test(T t);
    
  • 其他函数式接口

    • BiConsumer,功能和Consumer类似,只是多一个参数
    • BiPredicate,功能和Predicate类似,同样只是多了一个参数
    • BiFunction,功能和Function类似,同样只是多了一个参数
    • IntFunction、LongFunction、DobleFunction、ToIntFunction、ToLongFunction、ToDobleFunction 返回对应类型的数据
方法引用
  • 当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用

  • 方法引用是对Lambda的进一步简化,本质上就是Lambda表达式,而 Lambda 是函数式接口的实例,所以方法引用也是函数式接口的实例

  • 语法为: 类(对象): : 方法名

  • 方法引用 不需要方法的参数,调用可分为三种情况

    • 情况1,对象 : : 非静态方法
  • 情况2,类 : : 非静态方法 (在面向对象oop中是不允许的)

    • 情况3,类 : : 静态方法
    • 情况1和情况2 方法引用的要求:接口中的抽象方法的形参列表和返回值类型与方法引用的方法的形参列表和返回值类型完全相同

如下三种写法,从直接new到方法引用,代码的逻辑是完全一致的

    private static void extracted1() {Consumer<String> consumer =new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}};consumer.accept("写法1");}private static void extracted2() {Consumer<String> consumer= (s)->System.out.println(s);consumer.accept("写法2");}private static void extracted3() {//方法引用是对Lambda的进一步简化,用来替换Lambda表达式,因为System.out对象的println方法已经实现过了,所以只需要直接调用就好了,不需要重新实现//接口中的抽象方法的形参列表和返回值类型与方法引用的方法的形参列表和返回值类型完全相同,如下参数都是一个字符串,返回值都是void,所以可以使用参数引用Consumer<String> consumer= System.out::println;consumer.accept("写法3");}
构造器引用

类似与方法应用,参数列表和返回值匹配就可以使用构造器引用,因为构造器也是方法

类名::new

同理,数组引用,可以把数组看作一个类

    private static void extracted5() {//下面两种写法都是创建一个 10个长的数组Function<Integer,String[]> function = in-> new String[in];String[] apply = function.apply(10);Function<Integer,String[]> function1 = String[]::new;String[] apply1 = function1.apply(10);}
stream

Java8 Stream

  • 与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念。
  • Java 8 中的 Stream 是对集合(Collection)对象功能的增强,使用的是函数式编程模式,它可以被用来对集合进行链状流式的操作
  • 专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。
  • Stream 不会存储数据,也不会改变原对象,每次操作都回返回一个新的stream
  • Stream 分为顺序流和并行流

一个流式处理可以分为三个部分:

  • 获取一个数据源→ 数据转换 → 执行操作获取想要的结果,每次转换原有 Stream 对象不改变,返回一个新的 Stream 对象(可以有多次转换),这就允许对其操作可以像链条一样排列,变成一个管道。
转换成流
  • 创建流的五种方式:
    • 通过 stream 方法把 集合 或数组 (Arrays.stream())转换为流
    • 通过 Stream.of 方法直接传入多个元素构成一个流;( 例如:Stream.of(10,20,30); )
      • 通过 IntStream 或 DoubleStream 构造基本类型的流。( 例如:IntStream.of(10,20,30); )
    • 创建无限流,无限流的使用较少
      • 通过 Stream.iterate 方法使用迭代的方式构造一个无限流,然后使用 limit 限制流元素个数,
      • 通过 Stream.generate 方法从外部传入一个提供元素的 供应商来构造无限流,然后使用 limit 限制流元素个数
中间操作
  • 过滤:

    • filter,根据条件过滤

    • limit,操作也类似于SQL语句中的LIMIT关键字,不过相对功能较弱,limit返回包含前n个元素的流,当集合大小小于n时,则返回实际长度,

    • skip,操作与limit操作相反,如同其字面意思一样,是跳过前n个元素

    • distinct,操作类似于我们在写SQL语句时,添加的DISTINCT关键字,用于去重处理

      public class StreamEntity {private String name;private Integer age;private String high;
      }public static void test() {//向集合中初始化了一些 StreamEntity 对象,以供操作List<StreamEntity> list = getList();//过滤 年龄大于25的对象 ,后续使用lambda打印list.stream().filter(a -> a.getAge() > 25).forEach(a -> System.out.println(a));//截取 集合中前两条数据 ,后续使用方法引用打印list.stream().limit(2).forEach(System.out::println);//跳过前两条数据list.stream().skip(2).forEach(System.out::println);//筛选,通过对象的hashcode和equals对集合中的数据进行去重list.stream().distinct().forEach(System.out::println);}
      
  • 映射,包含两类映射操作:map和flatMap,就像sql可以仅输出我们需要的字段数据一样

    • map可以在filter筛选的基础之上,通过map将实体映射成为我们需要的字符串
    • flatMap与map的区别在于 flatMap是将一个流中的每个值都转成一个个流(流中的元素也有可能是流),然后再将这些流扁平化成为一个流,有点类似与集合的addAll,调用addAll向集合中添加集合,会把集合中的每一个参数都加到目标集合,而不是把集合对象加入到目标集合中
            //将元素中转换为其他形式或者提取信息 ,如下:提取对象中的年龄,并加1list.stream().map(a->a.getAge()+1).forEach(System.out::println);//flatMapList<List<StreamEntity>> res =new ArrayList<>();res.add(list);res.add(list);//这里已经把集合中的集合全部拆出来了Stream<String> objectStream = res.stream().flatMap(a -> a.stream().map(b->b.getName()));objectStream.forEach(System.out::println);
    
  • 排序

    • sorted(),进行自然排序,如果排序的对象没有实现 Comparator ,也就是没有排序规则,会报错

    • sorted(Comparator<? super T> comparator),如果排序的对象没有实现 Comparator ,也可以传入一个比较器

      //按照年龄自然排序
      list.stream().map(a->a.getAge()).sorted().forEach(System.out::println);//传入比较器
      list.stream().sorted((a, b) -> a.getAge() - b.getAge()).forEach(System.out::println);
      //使用方法引用为:
      list.stream().sorted(Comparator.comparingInt(StreamEntity::getAge)).forEach(System.out::println);
终止操作(终端操作)
  • 不调用终止操作,中间操作是不会执行的,调用终止操作产生结果后,stream就不能再被使用了

  • 查找

    • allMatch用于检测是否全部都满足指定的参数行为,如果全部满足则返回true
    • anyMatch则是检测是否存在一个或多个满足指定的参数行为,如果满足则返回true
    • noneMatch用于检测是否不存在满足指定行为的元素,如果不存在则返回true
    • findFirst用于返回满足条件的第一个元素,findFirst不携带参数,具体的查找条件可以通过filter设置
    • findAny相对于findFirst的区别在于,findAny不一定返回第一个,而是返回任意一个
    //
    boolean b = list.stream().map(a -> a.getAge()).allMatch(a -> a > 30);
    // 用于返回满足条件的第一个元素,查找条件可以通过filter设置
    Optional<Integer> first = list.stream().map(a -> a.getAge()).filter(a -> a > 30).findFirst();
    Integer integer = first.get()
    
    • count 返回流中的元素个数
    • max 返回流中的最大值
    • min 返回流中的最小值
    • forEach 内部迭代
    long count = list.stream().count();
    //根据自定义比较器求最大
    StreamEntity s1 = list.stream().max((a, b) -> a.getAge() - b.getAge()).get();
    //根据自定义比较器求最小
    StreamEntity s2 = list.stream().min((a, b) -> a.getAge() - b.getAge()).get();
    //迭代
    list.stream().forEach(a-> System.out.println(a.getAge()+1));
    
  • 归约

    • reduce 可以将流中的元素反复结合起来,得到一个值
    // 获取年龄的总和
    Integer s1 = list.stream().map(a -> a.getAge()).reduce((b, d) -> b + d).get();
    // reduce 的一个参数是初始值
    Integer s2 = list.stream().map(a -> a.getAge()).reduce(0, (b, d) -> b + d);
    
  • 收集

    • 归约 ,收集器也提供了相应的归约操作
    • collect 收集,需要用过Collectors中返回的Collector,将结果收集到指定的结果集中,例如 list、map、set 等
    //转换为 list
    List<StreamEntity> collect = list.stream().collect(Collectors.toList());
    //转化为 map
    Map<Integer, StreamEntity> collect1 = list.stream().collect(Collectors.toMap(a -> a.getAge(), a -> a));
    //转换为 set
    Set<String> collect2 = list.stream().map(a -> a.getName()).collect(Collectors.toSet());
  • 分组,在数据库操作中,我们可以通过GROUP BY关键字对查询到的数据进行分组,java8的流式处理也为我们提供了这样的功能,Collectors.groupingBy来操作集合

    • 分区,可以看做是分组的一种特殊情况,在分区中key只有两种情况:true或false,目的是将待分区集合按照条件一分为二
Optional
  • 参考 Google 的 Guava,用于尽量避免空指针异常
  • Optional 是一个容器类,用于保存任意类型的值,代表这个值存在,或者保存null,代表值不存在,

常见方法:

  • 创建Optional 对象

    • empty() 创建空的实例

    • of(T t),t不能为空

    • ofNullable(T t)

  • 获取Optional 对象的值

    • get方法会在值为null的时候抛出异常,可以用ifPresent()方法验证值是否为空
    • orElse()方法可以在创建实例时就指定返回的默认值

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

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

相关文章

nginx加权轮询,upstream,Keepalive,负载均衡实现案例

1. nginx 加权轮询, weight是权重配置。 #配置上游服务器 upstream tomcats {server 192.168.1.173:8080 weight=1;server 192.168.1.174:8080 weight=2;server 192.168.1.175:8080 weight=5; } server{liste

AWS Lambda 操作 RDS 示例

实现目标 创建一个 Lambda 接收调用时传入的数据, 写入 RDS 数据库 Post 表存储文章信息. 表结构如下: idtitlecontentcreate_date1我是标题我是正文内容2023-10-21 15:20:00 AWS 资源准备 RDS 控制台创建 MySQL 实例, 不允许 Public access (后面 Lambda 需要通过 VPC 访问…

AI的Prompt是什么

一.AI的Prompt的作用 在人工智能&#xff08;AI&#xff09;中&#xff0c;"Prompt"通常指的是向AI系统提供的输入或指令&#xff0c;用于引导AI进行特定的操作或生成特定的输出。例如&#xff0c;在一个对话型AI系统中&#xff0c;用户输入的问题就是一个prompt&…

【vue】使用less报错:显示this.getOptions is not a function

在vue-cli中使用 lang“less” 时报错&#xff1a; Module build failed: TypeError: this.getOptions is not a function at Object.lessLoader 原因&#xff1a;版本过高所致&#xff0c;所用版本为 解决&#xff1a;降低版本&#xff1a;npm install less-loader4.1.0 --s…

分类预测 | MATLAB实现SSA-CNN-BiGRU-Attention数据分类预测(SE注意力机制)

分类预测 | MATLAB实现SSA-CNN-BiGRU-Attention数据分类预测&#xff08;SE注意力机制&#xff09; 目录 分类预测 | MATLAB实现SSA-CNN-BiGRU-Attention数据分类预测&#xff08;SE注意力机制&#xff09;分类效果基本描述模型描述程序设计参考资料 分类效果 基本描述 1.MATLA…

kubeadm初始化搭建cri-dockerd记录 containerd.io

07.尚硅谷_搭建K8s集群&#xff08;kubeadm方式&#xff09;-部署master节点_哔哩哔哩_bilibili 视频里的版本只有1.17而现在&#xff08;2023.10.20&#xff09;kubernetes最新版本是1.28&#xff0c;需要搭载cri-dockerd&#xff0c; 先去网站下载了对应的rpm包cri-dockerd…

力扣每日一题69:x的平方根

题目描述&#xff1a; 给你一个非负整数 x &#xff0c;计算并返回 x 的 算术平方根 。 由于返回类型是整数&#xff0c;结果只保留 整数部分 &#xff0c;小数部分将被 舍去 。 注意&#xff1a;不允许使用任何内置指数函数和算符&#xff0c;例如 pow(x, 0.5) 或者 x ** 0…

Linux---(四)权限

文章目录 一、shell命令及运行原理1.什么是操作系统&#xff1f;2.外壳程序3.用户为什么不直接访问操作系统内核?4.操作系统内核为什么不直接把结果显示出来&#xff1f;非要加外壳程序&#xff1f;5.shell理解重点总结&#xff08;1&#xff09;shell是什么&#xff1f;&…

JDK8新特性:Stream流

目录 1.获取Stream流 2.Stream流常见的中间方法 3.Stream流常见的终结方法 1、 Stream 是什么&#xff1f;有什么作用&#xff1f;结合了什么技术&#xff1f; ●也叫 Stream 流&#xff0c;是Jdk8开始新增的一套 API ( java . util . stream .*)&#xff0c;可以用于操作集…

前端精度问题 (id 返回的和传给后端的不一致问题)

eg: 后端返回 id 10976458979374929 前端获取到的: 10976458979374928 原因: js 中 Number类型范围-2^53 1 到 2^53 - 1 Number.isSafeInteger()用来判断一个整数是否落在这个范围之内。 java中 Long 类型的取值范围是-2^63 1 到 2^63 - 1, 比JavaScript中大很多&#xff0…

Java开发-WebSocket

WebSocket是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工通信-浏览器和服务器只需要完成一次握手&#xff0c;两者之间就可以创建持久性的连接&#xff0c;并实现 双向数据传输。 使用 导入maven坐标 <dependency><groupId>org.springframework.bo…

基于V/F控制的三相逆变器MATLAB仿真模型

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 参考文献&#xff1a;张飞,刘亚,张玉杰.基于V/F控制的三相逆变器仿真模型的研究[J].自动化与仪器仪表,2015 关于V/F控制的论文非常多&#xff0c;随意下载&#xff01; 当分布式电源经过逆变器运行于孤岛模…

mysql聚合查询

在MySQL中&#xff0c;聚合查询是指通过一些特定的函数&#xff08;如SUM、AVG、MAX、MIN等&#xff09;根据需求来查询相关的信息。以下是一些MySQL聚合查询的例子&#xff1a; 使用SUM函数查询某列的总和&#xff1a; SELECT SUM(salary) FROM employees; 使用AVG函数查询…

【计算机毕设案例推荐】高校学术研讨信息管理系统小程序SpringBoot+Vue+小程序

前言&#xff1a;我是IT源码社&#xff0c;从事计算机开发行业数年&#xff0c;专注Java领域&#xff0c;专业提供程序设计开发、源码分享、技术指导讲解、定制和毕业设计服务 项目名 基于SpringBoot的高校学术研讨信息管理系统小程序 技术栈 SpringBoot小程序VueMySQLMaven 文…

UE4 材质实操记录

TexCoord的R通道是从左到右的递增量&#xff0c;G通道是从上到下的递增量&#xff0c;R通道减去0.5&#xff0c;那么左边就是【-0.5~0】区间&#xff0c;所以左边为全黑&#xff0c;Abs取绝对值&#xff0c;就达到一个两边向中间的一个递减的效果&#xff0c;G通道同理&#xf…

stm32外部时钟为12MHZ,修改代码适配

代码默认是8MHZ的&#xff0c;修改2个地方&#xff1a; 第一个地方是这个文件的这里&#xff1a; 第二个地方是找到这个函数&#xff1a; 修改第二个地方的这里&#xff1a;

javaEE -5(8000字详解多线程)

一&#xff1a;JUC(java.util.concurrent) 的常见类 1.1 ReentrantLock 可重入互斥锁. 和 synchronized 定位类似, 都是用来实现互斥效果, 保证线程安全&#xff0c;ReentrantLock 也是可重入锁. “Reentrant” 这个单词的原意就是 “可重入” ReentrantLock 的用法&#xf…

TypeScript学习 | 泛型

简介 泛型是指在定义函数、接口或类的时候&#xff0c;不预先指定具体的类型&#xff0c;而在使用的时候再指定类型的一种特性 作用 可以保证类型安全的前提下&#xff0c;让函数、接口或类与多种类型一起工作&#xff0c;从而实现复用 基本使用 举个例子&#xff1a; 创…

T113-S3-buildroot文件系统tar解压缩gz文件

目录 前言 一、现象描述 二、解决方案 三、tar解压缩.gz文件 总结 前言 本文主要介绍全志T113-S3平台官方SDK&#xff0c;buildroot文件系统tar不支持.gz文件解压缩的问题以及如何配置buildroot文件系统解决该问题的方法介绍。 一、现象描述 在buildroot文件系统中&#xff…

二、可行性分析与需求分析

文章目录 概念考点练习题一、可行性分析与需求分析1.可行性分析的任务2.可行性研究3.甘特图4.数据流图5.数据字典数据字典的内容 6.需求分析7. 实体联系ER图8. 状态转换图 二、练习题 概念考点练习题 一、可行性分析与需求分析 1.可行性分析的任务 用最小的代价在尽可能短的时…