java8函数式编程(Lambda表达式,Optional,Stream流)从入门到精通

news2024/12/23 11:24:49

文章目录

  • 函数式编程
    • Lambda表达式
    • Stream流
      • 创建流
      • 中间操作
      • 终结操作
      • 注意事项
    • Optional
      • 创建对象
        • 消费值
        • 获取值
        • 过滤
        • 判断
        • 数据转换
    • 方法引用
    • 高级用法
      • 基本数据类型优化
      • 并行流

函数式编程

  • 不关心具体的对象,只关心数据参数和 具体操作

Lambda表达式

  • 格式:

    • () -> {}
  • 假如接口只有一个 函数需要被重写,则可以使用 Lambda表达式来 代替 类的创建和重写

  • 省略规则:

    1. 参数类型可以省略
    2. 方法体只有一句代码时大括号return和唯一一句代码的分号可以省略
    3. 方法只有一个参数时小括号可以省略

Stream流

  • 对集合进行操作

创建流

  • 集合对象. stream()

  • 单列集合

    • 数组:

      • 使用 Arrays 数组工具类 来创建

      • 使用 stream.of创建

      • Integer[] arr = {1,2,3,4,5};
        Stream<Integer> stream = Arrays.stream(arr);
        Stream<Integer> stream2 = Stream.of(arr);
        
  • 双列集合:

    • 先转换为 Set<Map.Entry<String, String>>,再获取 Stream

    • Map<String ,String > map = new HashMap<>();
      Set<Map.Entry<String, String>> entries = map.entrySet();
      Stream<Map.Entry<String, String>> stream = entries.stream();
      

中间操作

  • distinct

    • 去重
      • 依靠 Objec.equals方法
        • 不重写是 地址相同
  • filter(条件)

    • 条件过滤

      • list.stream()
                .distinct() //过滤重复元素
                .filter(s -> s.length() <=3)
                .forEach(s -> System.out.println(s));
        
  • map

    • 转化集合中每个元素的类型:

      • List<String > list = new ArrayList<>();
        list.add("111");
        list.add("111");
        list.add("2222");
        // forEach
        //过滤条件
        list.stream()
                .map(s -> Integer.valueOf(s))
                .forEach(integer -> System.out.println(integer));
        
  • sorted 排序

    • 先将流中类型 转换为 Comparable

    • 如果是空参,自定义类型需要实现Comparable接口

      • List<String > list = new ArrayList<>();
        list.add("111");
        list.add("333");
        list.add("2222");
        // forEach
        //过滤条件
        list.stream()
                .sorted()
                .forEach(integer -> System.out.println(integer));
        
    • 还可以传入参数

      • list.stream()
                .map(s -> Integer.valueOf(s))
                .sorted(new Comparator<Integer>() {
                    @Override
                    public int compare(Integer o1, Integer o2) {
                        return o1-o2;
                    }
                })
                .forEach(integer -> System.out.println(integer));
        
  • limit:

    • 设置流的最大长度

      • list.stream()
                .limit(2)
                .forEach(System.out::println);
        
  • skip:

    • 跳过前n个元素

      • list.stream()
                .skip(2)
                .forEach(System.out::println);
        
  • flatMap

    • 将流中一个元素 转换成 流元素

      • List<List<String >> list = new ArrayList<>();
        list.add(Arrays.asList("111","2222"));
        list.add(Arrays.asList("1121","2222"));
        list.add(Arrays.asList("113","2222"));
        // forEach
        //过滤条件
        list.stream()
                .flatMap(strings -> strings.stream())
                .forEach(System.out::println);
        
        • 输出:

          • image-20231113143845889
        • 未简化:

          • //过滤条件
            list.stream()
                    .flatMap(new Function<List<String>, Stream<?>>() {
                        @Override
                        public Stream<?> apply(List<String> strings) {
                            return strings.stream();
                        }
                    })
                    .forEach(System.out::println);
            

终结操作

  • forEach

    • 对流中元素进行遍历操作
  • count:

    • 获取流中元素的 个数

      • long count = list.stream()
                .flatMap(strings -> strings.stream())
                .count();
        System.out.println(count);
        
  • min & max

    • 求流中最值

      • 重写比较方法:

        • Optional<Integer> count = list.stream()
                  .flatMap(strings -> strings.stream())
                  .map(s -> Integer.valueOf(s))
                  .max(new Comparator<Integer>() {
                      @Override
                      public int compare(Integer o1, Integer o2) {
                          return o1 - o2;
                      }
                  });
          System.out.println(count);
          
          • 简化:

            • Optional<Integer> count = list.stream()
                      .flatMap(strings -> strings.stream())
                      .map(s -> Integer.valueOf(s))
                      .max((o1, o2) -> o1 - o2);
              System.out.println(count);
              
  • collect:

    • 转换为list,使用 集合类中的 tolist方法:

      • List<List<String >> list = new ArrayList<>();
        list.add(Arrays.asList("111","2222"));
        list.add(Arrays.asList("1121","2222"));
        list.add(Arrays.asList("113","2222"));
        List<String> collect = list.stream()
                .flatMap(strings -> strings.stream())
                .collect(Collectors.toList());
        System.out.println(collect);
        
    • 转换为set,一样:

      • Set<String> collect = list.stream()
                .flatMap(strings -> strings.stream())
                .collect(Collectors.toSet());
        System.out.println(collect);
        
    • 转换为 Map集合

      • Map<String, String> collect = list.stream()
                .flatMap(strings -> strings.stream())
                .distinct()
                .collect(Collectors.toMap(s -> s, s -> s));
        System.out.println(collect);
        
  • 查找:

    • anyMatch

      • 任意一个满足就为 true

        • boolean b = list.stream()
                  .flatMap(strings -> strings.stream())
                  .anyMatch(s -> s.length() > 10);
          
    • allMatch

      • 所有满足才为true
    • noneMatch

      • 都不满足才为 true
  • 匹配:

    • findAny

      • 获取任意一个满足条件的 元素
    • findFirst

      • 获取第一个元素

        • List<List<String >> list = new ArrayList<>();
          list.add(Arrays.asList("111","2222"));
          list.add(Arrays.asList("1121","2222"));
          list.add(Arrays.asList("113","2222"));
          Optional<String> first = list.stream()
                  .flatMap(strings -> strings.stream())
                  .sorted()
                  .findFirst();
          first.ifPresent(System.out::println);
          
  • reduce归并

    • 对流中数据按照指定的计算方式计算出一个结果

    • 原理:

      • 两个参数的重载形式内部的计算方式如下:

        • image-20231113151352426
      • 一个参数:

        • 把第一个参数 作为 初始化值
        • image-20231113152846836
    • 使用:

      • 0 : 初始值

      • (result, integer2) -> result + integer2 执行的操作

      • List<List<String >> list = new ArrayList<>();
        list.add(Arrays.asList("111","2222"));
        list.add(Arrays.asList("1121","2222"));
        list.add(Arrays.asList("113","2222"));
        Integer reduce = list.stream()
                .flatMap(strings -> strings.stream())
                .map(s -> Integer.valueOf(s))
                .reduce(0, (result, integer2) -> result + integer2);
        

注意事项

  1. 惰性求值
    • 没有终结操作,中间操作不会执行
  2. 流是一次性的
    • 一个流只能执行一次 终结操作
  3. 不会影响原数据

Optional

  • 预防空指针异常

创建对象

  • 使用Optional.ofNullable

    • String s = new String("1");
      Optional<String> s1 = Optional.ofNullable(s);
      s1.ifPresent(s2 -> System.out.println(s2));
      
消费值
  • s1.ifPresent(s2 -> System.out.println(s2));
    
获取值
  • orElseGet

    • 为空则使用重写的 返回值

    • String s = null;
      Optional<String> s1 = Optional.ofNullable(s);
      System.out.println(s1.orElseGet(() -> "222"));
      
  • orElseThrow

    • 为空,则抛出异常
过滤
  • filter

    • 假如不满足过滤条件,则返回 Optional.empty

      • String s = "null";
        Optional<String> s1 = Optional.ofNullable(s);
        Optional<String> s2 = s1.filter(s3 -> s3.length() < 2);
        System.out.println(s2); //打印 Optional.empty
        
判断
  • isPresent
    • 判断是否存在
数据转换
  • 使用map 进行 Optional类型的转换

    • String s = "1";
      Optional<String> s1 = Optional.ofNullable(s);
      Optional<Integer> i = s1.map(s2 -> Integer.valueOf(s2));
      i.ifPresent(System.out::println); //1
      

方法引用

  • 在使用 Lambda 表达式的时候,如果方法体中只有一个方法 的调用话,就可以使用 类名或者对象名::方法名 来简化

高级用法

基本数据类型优化

  • 我们之前用到的很多Stream的方法由于都使用了泛型。

  • 所以涉及到的参数和返回值都是引用数据类型。

  • 即使我们操作的是整数小数,但是实际用的都是他们的包装类

  • JDK5中引入的自动装箱和自动拆箱让我们在使用对应的包装类时就好像使用基本数据类型一样方便。

  • 但是你一定要知道装箱和拆箱肯定是要消耗时间的。

  • 虽然这个时间消耗很下。但是在大量的数据不断的重复装箱拆箱的时候,你就不能无视这个时间损耗了。

  • 所以为了让我们能够对这部分的时间消耗进行优化。

  • Stream还提供了很多专门针对基本数据类型的方法。

  • 例如: mapToInt,mapToLong,mapToDouble,flatMapTolnt,flatMapToDouble等。

    • List<List<String >> list = new ArrayList<>();
      list.add(Arrays.asList("111","2222"));
      list.add(Arrays.asList("1121","2222"));
      list.add(Arrays.asList("113","2222"));
      list.stream()
              .flatMap(strings -> strings.stream())
              .mapToInt(s -> Integer.valueOf(s))
              .forEach(System.out::println);
      

并行流

  • 当流中有大量元素时,我们可以使用并行流去提高操作的效率。其实并行流就是把任务分配给多个线程去完全。

  • 如果我们自己去用代码实现的话其实会非常的复杂,并且要求你对并发编程有足够的理解和认识。

  • 而如果我们使用Stream的话,我们只需要修改一个方法的调用就可以使用并行流来帮我们实现,从而提高效率。

  • 使用parallel()

    • peek中间操作

    • List<List<String >> list = new ArrayList<>();
      list.add(Arrays.asList("111","2222"));
      list.add(Arrays.asList("1121","2222"));
      list.add(Arrays.asList("113","2222"));
      OptionalInt first = list.stream()
          .parallel()
          .flatMap(strings -> strings.stream())
          .mapToInt(s -> Integer.valueOf(s))
          .peek(i -> System.out.println(i + ":" + Thread.currentThread().getName()))
          .findFirst();
      
      • 打印:
        • image-20231113163806329

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

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

相关文章

基于缎蓝园丁鸟算法优化概率神经网络PNN的分类预测 - 附代码

基于缎蓝园丁鸟算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于缎蓝园丁鸟算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于缎蓝园丁鸟优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针…

css3 初步了解

1、css3的含义及简介 简而言之&#xff0c;css3 就是 css的最新标准&#xff0c;使用css3都要遵循这个标准&#xff0c;CSS3 已完全向后兼容&#xff0c;所以你就不必改变现有的设计&#xff0c; 2、一些比较重要的css3 模块 选择器 1、标签选择器&#xff0c;也称为元素选择…

C++算法: 最大化数组末位元素的最少操作次数

涉及知识点 数学 题目 给你两个下标从 0 开始的整数数组 nums1 和 nums2 &#xff0c;这两个数组的长度都是 n 。 你可以执行一系列 操作&#xff08;可能不执行&#xff09;。 在每次操作中&#xff0c;你可以选择一个在范围 [0, n - 1] 内的下标 i &#xff0c;并交换 num…

MyBatis 知识总结

1 MyBatis 1.1 简介 持久层框架&#xff0c;用于简化JDBC开发 JavaEE三层架构&#xff1a;表现层、业务层、持久层 表现层&#xff1a;做页面展示 业务层&#xff1a;做逻辑处理 持久层&#xff1a;负责将数据保存到数据库的那一层代码 框架&#xff1a;半成品软件&#xff0…

软件外包开发的需求对接

软件外包开发的成功与否很大程度上取决于需求对接的有效性。以下是一些建议&#xff0c;可帮助您在软件外包开发中进行需求对接&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.明确业务目标和需求&…

CSDN每日一题学习训练——Java版(字符串相乘、子集、删除链表的倒数第 N 个结点)

版本说明 当前版本号[20231112]。 版本修改说明20231112初版 目录 文章目录 版本说明目录字符串相乘题目解题思路代码思路补充说明参考代码 子集题目解题思路代码思路参考代码 删除链表的倒数第 N 个结点题目解题思路代码思路参考代码 字符串相乘 题目 给定两个以字符串形…

解决谷歌浏览器卸载后重装失败谷歌浏览器无法更新

一.谷歌浏览器卸载后重装失败 大多数情况都是卸载残留导致的。所以要去清理注册表。 winR&#xff0c;然后输入regedit&#xff0c;启动注册表&#xff0c;HKEY_CURRENT_USER/HKEY_CURRENT_USER/Software中的Google文件夹删除即可&#xff0c;然后重启电脑&#xff0c;如果还…

二、数据运营:B-O价值模型

B - O 价值模型&#xff0c;即 Business - Operation 模型&#xff0c;业务一运营模型。这是一个非常成熟的概念&#xff0c;其变体 BOSS 系统&#xff0c;即 BSS 业务支撑系统和 OSS 运营支撑系统已经在通信运营上使用20多年之久。 B - O 价值模型试图建立起一种通用的业务经…

工作记录--(用HTTPS,为啥能被查出浏览记录?如何解决?)---每天学习多一点

由于网络通信有很多层&#xff0c;即使加密通信&#xff0c;仍有很多途径暴露你的访问地址&#xff0c;比如&#xff1a; DNS查询&#xff1a;通常DNS查询是不会加密的&#xff0c;所以&#xff0c;能看到你DNS查询的观察者&#xff08;比如运营商&#xff09;是可以推断出访问…

区块链拆分

随着区块链技术的发展和普及&#xff0c;去中心化钱包逐渐成为数字货币领域的重要工具。去中心化钱包不仅具有高度安全性和隐私保护能力&#xff0c;还可以通过智能合约和开源技术实现定制化功能。本文将探讨去中心化钱包定制开发的基本概念、优势、流程和前景。 一、去中心化钱…

Linux下的文件系统

文章目录 一、初始文件系统 二、理解磁盘文件 三、了解磁盘 四、深入理解磁盘文件 4、1 磁盘分区 4、2 分区存储细节 4、3 磁盘文件的操作 4、3、1 查找某个磁盘文件 4、3、2 创建文件 4、3、3 对文件进行写入 4、3、4 删除文件 4、4 再次理解文件权限 &#x1f64b;‍♂️ 作…

MCU通过KT6368A用SPP透传发送1K左右的数据,手机APP显示是3个包或者4个包,但是我看手册说最大一个包是512,理论应该是两个包吧,请问这正常吗?

一、问题简介 MCU通过KT6368A用SPP透传发送1K左右的数据&#xff0c;手机APP显示是3个包或者4个包&#xff0c;但是我看手册说最大一个包是512&#xff0c;理论应该是两个包吧&#xff0c;请问这正常吗&#xff1f; 详细说明 实际测试的截图如下&#xff1a;使用的是安卓app…

【设计原则篇】聊聊开闭原则

开闭原则 其实就是对修改关闭&#xff0c;对拓展开放。 是什么 OCP&#xff08;Open/Closed Principle&#xff09;- 开闭原则。关于开发封闭原则&#xff0c;其核心的思想是&#xff1a;模块是可扩展的&#xff0c;而不可修改的。也就是说&#xff0c;对扩展是开放的&#xf…

《哈佛商业评论》:CRM实施为什么成功率低?

《哈佛商业评论》研究表明&#xff0c;三分之一的CRM客户管理系统实施以失败告终。CRM实施为什么成功率较低&#xff1f;研究发现&#xff0c;CRM实施失败的主要原因在于&#xff1a;CRM系统目标不清晰&#xff0c;重点不明确&#xff0c;操作过于复杂&#xff0c;给一线用户带…

NIO的浅了解

一、五种IO类型 1、阻塞IO 用户进程一直等待数据准备好&#xff0c;在复制完成之前都是阻塞的 2、非阻塞IO 用户进程需要不断轮询查看是否数据准备好 优化了提升并发连接数量&#xff0c;但是每一个请求都需要创建一个socket建立连接&#xff0c;每个线程都需要去遍历轮询&am…

ZooKeeper+Kafka+ELK+Filebeat集群搭建实现大批量日志收集和展示

大致流程&#xff1a;将nginx 服务器&#xff08;web-filebeat&#xff09;的日志通过filebeat收集之后&#xff0c;存储到缓存服务器kafka&#xff0c;之后logstash到kafka服务器上取出相应日志&#xff0c;经过处理后写入到elasticsearch服务器并在kibana上展示。 一、集群环…

4、创建第一个鸿蒙应用

一、创建项目 此处以空模板为例来创建一个鸿蒙应用。在创建项目前请保持网页的畅通。 1、在欢迎页面点击“Create Project”。 2、左侧默认为“Application”&#xff0c;在“Template Market”中选择空模板&#xff08;Empty Ability&#xff09;&#xff0c;点击“Next” 3…

Redhat Linux v8.2 实时内核环境配置及参数调优

BC-Linux V8.2 实时内核环境配置及参数调优 -------物理机 & 虚拟机 一、前言 本文档包含有关Redhat Linux for Real Time的基本安装和调试信息。许多行业和组织需要极高性能的计算&#xff0c;并且可能需要低且可预测的延迟&#xff0c;尤其是在金融和电信行业中。延迟&…

FAB天车系统OHT 介绍

1.技术背景&#xff1a; “OHT”是Overhead Hoist Transport的简称&#xff0c;是指能够在空中轨道上行驶&#xff0c;并能够通过皮带传动起重机构“直接”进入保管设备或工艺设备的装卸口&#xff0c;应用于工序区内部运输&#xff0c;也应用于工序区间或工厂间运输。 “OHT…

VMware ubuntu 新虚拟机的创建

根据自己指定的路径安装好vm后。 创建新的虚拟机。 记录一下&#xff0c;下次用到别再忘记了。 如需转载&#xff0c;注明出处&#xff01; 点赞收藏关注我 以资鼓励 打开vm 软件&#xff0c;点击创建新的虚拟机 选择典型&#xff0c;点击下一步 选择你的ubuntu镜像iso文件 …