Java基础知识——lamda表达式和函数式接口

2023-11-05


一、Lambda表达式

函数式接口:任何接口,如果只包含唯一一个抽象方法,那么它就是一个函数式接口。对于函数式接口,可以通过Lambda表达式节创建该接口的对象。

使用Lambda表达式:避免匿名内部类定义过多、可以让代码看起来更简洁、去掉了一对没有意义的代码只留下了核心的逻辑

原来:

package Lambda;

public class TestLambda1 {
    public static void main(String[] args) {
        ILike like = new Like();
        like.lambda();
    }
}

//1、定义一个函数式接口
interface ILike{
    void lambda();
}

//2、实现类
class Like implements ILike {
    public void lambda(){
        System.out.println("I like lambda");
    }
}

通过匿名内部类简化:

package Lambda;

public class TestLambda1 {
    public static void main(String[] args) {
        ILike like = new ILike(){
            public void lambda(){
                System.out.println("I like lambda");
            }
        };
        like.lambda();
    }
}

//1、定义一个函数式接口
interface ILike{
    void lambda();
}



通过Lambda表达式进一步简化:

package Lambda;

public class TestLambda1 {
    public static void main(String[] args) {
       ILike like = ()->{
           System.out.println("I like lambda");
       };
       like.lambda();
    }
}

//1、定义一个函数式接口
interface ILike{
    void lambda();
}



总结:对于只包含一个抽象方法的接口,就可以用Lambda表达式简化代码创建对象

进一步省略:

  • 参数类型可以省略
  • 方法体只有一句代码的时候,可以省略大括号return和分号
  • 方法只有一个参数的时候可以省略小括号
       ILike like = ()->System.out.println("I like lambda");

二、函数式接口

函数式接口指的是有且只有一个抽象方法的接口,但是也可以有其他的方法(默认、静态、私有)。

可以添加@FunctionalInterface注解,作用是检测一个接口是否是函数式接口

2.1 函数式接口作用

函数式接口一般可以作为方法的参数和返回值类型

作为方法的参数:

package Lambda;

public class TestLambda1 {
    public static void show(MyFunctionalInterface myInter){
        myInter.method();
    }

    public static void main(String[] args) {
        show(()->System.out.println("重写接口中的方法"));
    }
}

@FunctionalInterface
interface MyFunctionalInterface{
    public void method();
}


作为方法的返回值类型:可以直接返回一个Lambda表达式

package Lambda;

import java.util.Arrays;
import java.util.Comparator;

public class TestLambda1 {
    public static Comparator<String> getComparator(){
        return (o1,o2) -> o2.length()-o1.length();
    }
    public static void main(String[] args) {
        String[] arr = {"aaa","b","cccccc","dddddddddd"};
        System.out.println(Arrays.toString(arr));
        Arrays.sort(arr,getComparator());//按照长度排序
        System.out.println(Arrays.toString(arr));
    }
}




2.2 常用函数式接口——Supplier接口

java.util.function.Supplier< T >接口仅包含一个无参的方法:T get()。用来获取一个泛型参数指定类型的对象数据。由于这是一个函数式接口,这也就意味着对应的Lambda表达式需要向外提供一个符合泛型类型的对象数据。这个接口被称为生产型接口,即指定接口的泛型是什么类型,那么接口中的get方法就会产生什么类型的数据。

样例:

package Lambda;

import java.util.function.Supplier;

public class DemoSupplier {
    public static String getString(Supplier<String> sup){
        return sup.get();
    }

    public static void main(String[] args) {
        String s = getString(()->"胡歌");
        System.out.println(s);
    }
}

练习:使用Supplier接口作为方法参数类型,通过Lambda表达式求出int数组中的最大值。

package Lambda;

import java.util.function.Supplier;

public class DemoSupplier {
    public static int getMax(Supplier<Integer> sup){
        return sup.get();
    }

    public static void main(String[] args) {
        int[] arr = {100,0,0-50,88,99,33,-30};
        int maxValue = getMax(()->{
          int max = arr[0];
          for(int i :arr){
              if(i > max)
                  max = i;
          }
          return max;
        });
        System.out.println(maxValue);
    }
}

2.3 常用函数式接口——Consumer接口

java.util.function.consumer< T >接口正好与Supplier接口相反,它消费一个数据,其数据类型由泛型决定。它包含抽象方法void accept(T t),意为消费一个指定泛型的数据。

accept()方法的使用:

package Lambda;

import java.util.function.Consumer;

public class DemoConsumer {
    public static void method(String name , Consumer<String> con){
        con.accept(name);
    }

    public static void main(String[] args) {
        method("赵丽颖",(String name)->{
            //消费方式:把字符串进行翻转输出
            String reName = new StringBuffer(name).reverse().toString();
            System.out.println(reName);
        });
    }
}

在这里插入图片描述

Consumer接口中的默认方法andThen:如果一个方法的参数和返回值都是Consumer类型,那么就可以实现消费数据的时候,首先做一个操作,然后再做一个操作,实现组合。这个方法就是由andThen实现的。要向实现组合,需要两个或者多个Lambda表达式即可,而andThen语义正是一步接一步操作。例如:

Consumer<String> con1
Consumer<String> con2
String s = "hello";
con1.accept(s);
con2.accept(s);

可以用andThen来进行连接,再进行消费,谁写前面谁先消费,所以下面是con1先进行消费:
con1.andThen(con2).accept(s);

第一种方式:

第一种方式:
package Lambda;

import java.util.Locale;
import java.util.function.Consumer;

public class DemoConsumer {
    public static void method(String s , Consumer<String> con1 , Consumer<String> con2){
        con1.accept(s);
        con2.accept(s);
    }

    public static void main(String[] args) {
        method("hello",
                (t)->{
                    System.out.println(t.toUpperCase());
                },
                (t)->{
                    System.out.println(t.toLowerCase());
                });

    }
}


第二种方式:用andThen进行连接

package Lambda;

import java.util.Locale;
import java.util.function.Consumer;

public class DemoConsumer {
    public static void method(String s , Consumer<String> con1 , Consumer<String> con2){
        con1.andThen(con2).accept(s);
    }

    public static void main(String[] args) {
        method("hello",
                (t)->{
                    System.out.println(t.toUpperCase());
                },
                (t)->{
                    System.out.println(t.toLowerCase());
                });

    }
}

练习:下面的字符串数组中存有多条信息,请按照格式“姓名:XX,性别:XX”的格式将信息打印出来,要求将打印姓名的动作作为第一个Consumer接口的Lambda实例,将打印性别的动作作为第二个Consumer接口的Lambda实例,将两个Consumer接口按照顺序拼接到一起:

package Lambda;

import java.util.Locale;
import java.util.function.Consumer;

public class DemoConsumer {
   public static void printInfo(String[] arr , Consumer<String> con1 , Consumer<String> con2){
       for(String message : arr){
           con1.andThen(con2).accept(message);
       }
   }

    public static void main(String[] args) {
        String[] arr = {"迪丽热巴,女","古力娜扎,女","马尔扎哈,男"};

        printInfo(arr,(message)->{
            String name = message.split(",")[0];
            System.out.print("姓名:"+name+",");
        },(message)->{
            String gender = message.split(",")[1];
            System.out.println("性别:"+gender);
        });
    }
}

在这里插入图片描述

2.4 常用函数式接口——Predicate接口

有时候我们需要对某种数据的类型进行判断,从而得到一个boolean值结果。这是可以用java.util.function.Predicate< T >接口。

抽象方法test():

package Lambda;

import java.util.function.Predicate;

public class DemoPredicate {
    public static boolean checkString(String s , Predicate<String> pre){
        return pre.test(s);
    }

    public static void main(String[] args) {
        String s = "abcdef";
        //对参数传递的字符串进行判断,判断字符串长度是否大于5
        boolean b = checkString(s,str->str.length()>5);
        System.out.println(b);
    }
}

既然是条件判断,那么就会存在与或非三种逻辑。

与逻辑:默认方法and()

package Lambda;

import java.util.function.Predicate;

public class DemoPredicate {
   /*
        定义一个方法,方法的参数,传递一个字符串,两个Predicate接口
            一个用于判断字符串长度是否大于5
            一个用于判断字符串中是否包含a
            两个条件必须同时满足
    */
    public static boolean checkString(String s , Predicate<String> pre1 , Predicate<String> pre2){
        return pre1.and(pre2).test(s);
    }

    public static void main(String[] args) {
        String s = "bcdeff";

        boolean b = checkString(s,(String str)->{
            return str.length()>5;
        },(String str)->{
            return str.contains("a");
        });
        System.out.println(b);
    }
}

或逻辑:默认方法or()

package Lambda;

import java.util.function.Predicate;

public class DemoPredicate {
   /*
        定义一个方法,方法的参数,传递一个字符串,两个Predicate接口
            一个用于判断字符串长度是否大于5
            一个用于判断字符串中是否包含a
            满足一个条件即可
    */
    public static boolean checkString(String s , Predicate<String> pre1 , Predicate<String> pre2){
        return pre1.or(pre2).test(s);
    }

    public static void main(String[] args) {
        String s = "bcdeff";

        boolean b = checkString(s,(String str)->{
            return str.length()>5;
        },(String str)->{
            return str.contains("a");
        });
        System.out.println(b);
    }
}

非逻辑:negate()

package Lambda;

import java.util.function.Predicate;

public class DemoPredicate {
   /*
        定义一个方法,方法的参数,传递一个字符串,一个Predicate接口
           如果字符串长度大于5,则返回false
           如果字符串长度不大于5,则返回true
    */
    public static boolean checkString(String s , Predicate<String> pre){
        return pre.negate().test(s);
    }

    public static void main(String[] args) {
        String s = "bcdeff";

        boolean b = checkString(s,str->str.length()>5);
        System.out.println(b);
    }
}

2.5 常用函数式接口——Function接口

java.util.function.Function< T , R >接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件。将T的数据类型转换为R的数据类型

抽象方法R apply(T t),根据类型T的参数获取类型R的结果

package Lambda;

import java.util.function.Function;

public class DemoFunction {
    /*
        定义一个方法
        方法的参数传递一个字符串类型的证书
        方法的参数传递一个Function接口,泛型使用<String,Integer>
        使用Function接口中的方法apply,把字符串类型的整数转换为Integer类型
     */
    public static void change(String s , Function<String,Integer> fun){
        int in = fun.apply(s);
        System.out.println(in);
    }

    public static void main(String[] args) {
        String s = "1234";
        change(s,str->Integer.parseInt(s));
    }
}

默认方法andThen:进行组合操作

package Lambda;

import java.util.function.Function;

public class DemoFunction {
    /*
        需求:把String类型的“123”转换为Integer类型,把转换后的结果加10
            把增加之后的Integer类型的数据转换为String类型

        分析:转换了两次
            第一次是Function<String,Integer> fun1:
                Integer i = fun1.apply("123")+10
            第二次是Function<Integer,String> fun2:
                String s = fun2.apply(i)
            我们可以使用andThen方法将两次转换组合在一起使用
                String s = fun1.andThen(fun2).apply("123")

     */
    public static void change(String s , Function<String,Integer> fun1 , Function<Integer,String> fun2){
        String ss = fun1.andThen(fun2).apply(s);
        System.out.println(ss);
    }

    public static void main(String[] args) {
        String s = "123";
        change(s,str->Integer.parseInt(str)+10,i->i+"");
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java基础知识——lamda表达式和函数式接口 的相关文章

  • Java new Date() 打印

    刚刚学习 Java 我知道这可能听起来很愚蠢 但我不得不问 System out print new Date 我知道参数中的任何内容都会转换为字符串 最终值是 new Date 返回对 Date 对象的引用 那么它是如何打印这个的呢 Mo
  • 如何使用 Java 和 Selenium WebDriver 在 C 目录中创建文件夹并需要将屏幕截图保存在该目录中?

    目前正在与硒网络驱动程序和代码Java 我有一种情况 我需要在 C 目录中创建一个文件夹 并在该文件夹中创建我通过 selenium Web 驱动程序代码拍摄的屏幕截图 它需要存储在带有时间戳的文件夹中 如果我每天按计划运行脚本 所有屏幕截
  • 如何默认将 Maven 插件附加到阶段?

    我有一个 Maven 插件应该在编译阶段运行 所以在项目中consumes我的插件 我必须做这样的事情
  • Play框架运行应用程序问题

    每当我尝试运行使用以下命令创建的新 Web 应用程序时 我都会收到以下错误Play http www playframework org Error occurred during initialization of VM Could no
  • 在 java 类和 android 活动之间传输时音频不清晰

    我有一个android活动 它连接到一个java类并以套接字的形式向它发送数据包 该类接收声音数据包并将它们扔到 PC 扬声器 该代码运行良好 但在 PC 扬声器中播放声音时会出现持续的抖动 中断 安卓活动 public class Sen
  • Java JDBC:更改表

    我希望对此表进行以下修改 添加 状态列 varchar 20 日期列 时间戳 我不确定该怎么做 String createTable Create table aircraft aircraftNumber int airLineCompa
  • Final字段的线程安全

    假设我有一个 JavaBeanUser这是从另一个线程更新的 如下所示 public class A private final User user public A User user this user user public void
  • 加速代码 - 3D 数组

    我正在尝试提高我编写的一些代码的速度 我想知道从 3d 整数数组访问数据的效率如何 我有一个数组 int cube new int 10 10 10 我用价值观填充其中 然后我访问这些值数千次 我想知道 由于理论上所有 3d 数组都存储在内
  • 列出jshell中所有活动的方法

    是否有任何命令可以打印当前 jshell 会话中所有新创建的方法 类似的东西 list但仅适用于方法 您正在寻找命令 methods all 它会打印所有方法 包括启动 JShell 时添加的方法 以及失败 被覆盖或删除的方法 对于您声明的
  • JavaMail 只获取新邮件

    我想知道是否有一种方法可以在javamail中只获取新消息 例如 在初始加载时 获取收件箱中的所有消息并存储它们 然后 每当应用程序再次加载时 仅获取新消息 而不是再次重新加载它们 javamail 可以做到这一点吗 它是如何工作的 一些背
  • 磁模拟

    假设我在 n m 像素的 2D 表面上有 p 个节点 我希望这些节点相互吸引 使得它们相距越远吸引力就越强 但是 如果两个节点之间的距离 比如 d A B 小于某个阈值 比如 k 那么它们就会开始排斥 谁能让我开始编写一些关于如何随时间更新
  • Spring @RequestMapping 带有可选参数

    我的控制器在请求映射中存在可选参数的问题 请查看下面的控制器 GetMapping produces MediaType APPLICATION JSON VALUE public ResponseEntity
  • 斯坦福 NLP - 处理文件列表时 OpenIE 内存不足

    我正在尝试使用斯坦福 CoreNLP 中的 OpenIE 工具从多个文件中提取信息 当多个文件 而不是一个 传递到输入时 它会给出内存不足错误 All files have been queued awaiting termination
  • Java按日期升序对列表对象进行排序[重复]

    这个问题在这里已经有答案了 我想按一个参数对对象列表进行排序 其日期格式为 YYYY MM DD HH mm 按升序排列 我找不到正确的解决方案 在 python 中使用 lambda 很容易对其进行排序 但在 Java 中我遇到了问题 f
  • 在两个活动之间传输数据[重复]

    这个问题在这里已经有答案了 我正在尝试在两个不同的活动之间发送和接收数据 我在这个网站上看到了一些其他问题 但没有任何问题涉及保留头等舱的状态 例如 如果我想从 A 类发送一个整数 X 到 B 类 然后对整数 X 进行一些操作 然后将其发送
  • 如何在 javadoc 中使用“<”和“>”而不进行格式化?

    如果我写
  • AWS 无法从 START_OBJECT 中反序列化 java.lang.String 实例

    我创建了一个 Lambda 函数 我想在 API 网关的帮助下通过 URL 访问它 我已经把一切都设置好了 我还创建了一个application jsonAPI Gateway 中的正文映射模板如下所示 input input params
  • 获取 JVM 上所有引导类的列表?

    有一种方法叫做findBootstrapClass对于一个类加载器 如果它是引导的 则返回一个类 有没有办法找到类已经加载了 您可以尝试首先通过例如获取引导类加载器呼叫 ClassLoader bootstrapLoader ClassLo
  • 使用 JMF 创建 RTP 流时出现问题

    我正处于一个项目的早期阶段 需要使用 RTP 广播DataStream创建自MediaLocation 我正在遵循一些示例代码 该代码目前在rptManager initalize localAddress 出现错误 无法打开本地数据端口
  • 如何修复 JNLP 应用程序中的“缺少代码库、权限和应用程序名称清单属性”?

    随着最近的 Java 更新 许多人都遇到了缺少 Java Web Start 应用程序的问题Codebase Permissions and Application name体现属性 尽管有资源可以帮助您完成此任务 但我找不到任何资源综合的

随机推荐

  • 第2章 数据库关系模型-单元测验-数据库原理及应用

    第2章 数据库关系模型 数据库与机器学习 作业 常用的关系查询操作包括选择 投影 连接 并 交等 v 实体完整性是指关系表的属性组成必须是完整的 x 自然连接是一种等值连接 v 在参照完整性中 可以定义级联操作 v 用户自定义完整性可以实施
  • XPath应用案例

    爬取CSDN学院一级标题 打开网站 https edu csdn net 在一级标题 人工智能 单击右键 gt 检查 在弹出的开发者模式中标灰的就是检查的元素 往上看 a 地址就是我们点击人工智能跳转的页面 如果不确认是不是我们可以点击下看
  • DCDC基础(2)--BUCK芯片的各个引脚是什么意思?带你深入了解BUCK电源的稳压原理

    最近开通了公众号 射频工程师的日常 有文章更新 刚兴趣可以关注一下 谢谢 上一节带大家了解了一下BUCK电路的基本原理 硬件交流群里面刚接触硬件的同学在看BUCK有关的原理图时一脸疑惑 BUCK芯片外围怎么多了几个电阻 这些电阻是用来干什么
  • 使用Pytorch对创建的数据进行分类(具体为三分类)

    作业代码截图以及结果显示 下面是基于二分类实现对数据三分类的步骤 1 首先创建数据 代码如下 import torch from torch autograd import Variable import matplotlib pyplot
  • 【深度学习工作站】Ubuntu18.04安装 + 2080Ti 驱动安装

    一 系统安装 下载Ubuntu18 04镜像 下载rufus 制作启动盘U盘 主要参考 https blog csdn net weixin 43818251 article details 90726219 二 显卡独立驱动 刚开始我参考
  • SO、SOP、SOIC、MSOP、TSSOP、TSOP、VSSOP、SSOP、SOJ封装详解

    1 简要信息如下 2 SOP和SOIC的规格多是类似的 现在大多数厂商基本都采用的是SOIC的描述 SOIC8有窄体150mil的 外形封装宽度 不含管脚 下同 管脚间距是1 27mm 如下 有宽体的208mil的 管脚间距是1 27mm
  • [ali编程题练习] 小强去春游

    小强作为强班的班长 决定带着包含他在内的n个同学去春游 路程走到一半 发现前面有一条河流 且只有一条小船 经过实验后发现 这个小船一次最多只能运送两个人 而且过河的时间是等于两个人中体重较大的那个人的体重 如果只有一个人 那么过河时间就是这
  • 陈天奇等人提出TVM:深度学习自动优化代码生成器

    TVM 是由华盛顿大学在读博士陈天奇等人提出的深度学习自动代码生成方法 去年 8 月机器之心曾对其进行过简要介绍 该技术能自动为大多数计算硬件生成可部署优化代码 其性能可与当前最优的供应商提供的优化计算库相比 且可以适应新型专用加速器后端
  • less和css的区别是什么

    一 less与css介绍 Less 是一门 CSS 预处理语言 它扩展了 CSS 语言 增加了变量 Mixin 函数等特性 使 CSS 更易维护和扩展 LESS是一个CSS预处理器 可以为网站启用可自定义 可管理和可重用的样式表 LESS是
  • 力扣算法题

    1 合并两个有序数组 简单 给你两个有序整数数组 nums1 和 nums2 请你将 nums2 合并到 nums1 中 使 nums1 成为一个有序数组 初始化 nums1 和 nums2 的元素数量分别为 m 和 n 你可以假设 num
  • 今天来聊聊笔记本电脑的使用禁忌

    随着科技的不断进步 笔记本电脑已经成为我们生活 学习和工作中不可或缺的一部分 然而 在享受便携性和高效性的同时 我们也需要注意一些使用禁忌 以保护我们的笔记本电脑 延长其使用寿命 本文将从四个方面为您介绍笔记本电脑使用的禁忌 第一部分 不透
  • UEFI启动U盘制作

    说明 在网上搜索了一下UEFI启动U盘工具 发现都是一些超级大的工具 动不动就是上百兆 而且之前使用老毛桃安装系统 发现会在系统中安装很多其他的软件 心有余悸 所以打算找一个干净的工具 随后在网上搜索找到rufus 使用 下载rufus h
  • QObject::connect()函数使用的几个注意点

    一 connect 函数有且只能在QObject类里面和QObject派生类里面使用 connect 函数有且只能在QObject类里面和QObject派生类里面使用 自己新建的类里面 基类不是QObject类和其QObject派生类 使用
  • html 怎么做到大小屏兼容,CSS兼容各个屏幕大小的写法

    media screen and max width 1100px 此处写最大屏幕是1100px的css media screen and max width 978px 此处写最大屏幕是978px的css media screen and
  • 一文读懂Embedding

    文章目录 一 什么是Embedding 二 One Hot编码 三 怎么理解Embedding 四 Word Embedding 一 什么是Embedding Embedding 直译是嵌入式 嵌入层 简单来说 我们常见的地图就是对于现实地
  • win10下用tensorflow object detection API训练自己的数据出错

    gtf36 D models master models research object detection gt python model main py pipeline config path mytraining faster rc
  • 人脸识别项目介绍

    项目介绍 人脸识别 从Python或命令行中识别和操作面部 世界上最简单的人脸识别库 使用dlib的最新人脸识别功能构建 建立在深度学习之上 该模型的精度为99 38 Wild 基准中的标记面孔 这也提供了一个简单的face recogni
  • 论文学习笔记:Generalized Intersection over Union: A Metric and A Loss for Bounding Box Regressi

    Generalized Intersection over Union A Metric and A Loss for Bounding Box Regression 作者 Hamid Rezatofighi Nathan Tsoi Jun
  • STM32/STM8+DMX512协议

    标准DMX512协议 https blog csdn net qq 42992084 article details 98525578 这位大佬有详细介绍 因为标准DMX512协议在现有的MCU上很难达到或者说很浪费资源 所以大多采用非标准
  • Java基础知识——lamda表达式和函数式接口

    文章目录 一 Lambda表达式 二 函数式接口 2 1 函数式接口作用 2 2 常用函数式接口 Supplier接口 2 3 常用函数式接口 Consumer接口 2 4 常用函数式接口 Predicate接口 2 5 常用函数式接口 F