01-详细介绍函数式接口和Lambda表达式语法

news2024/11/16 17:48:18

函数式接口介绍

如果在一个接口中只声明了一个抽象方法,则此接口就被称为函数式接口(该接口可以包含其他非抽象方法)

  • 接口上使用@FunctionalInterface注解可以验证该接口是否为函数式接口,javadoc生成的文档时也会保留该注解, 若接口中有多个抽象方法编译器会报错

随着Python,Scala等语言的兴起和新技术的挑战,Java不得不做出调整以便支持更加广泛的技术要求,所以Java8不但可以支持OOP还可以支持OOF(面向函数编程)

  • 面向对象编程思想:完成一件事情需要找一个能解决这个事情的对象然后调用对象的方法
  • 函数式编程思想: 重视结果不重视过程,只要能获取到结果即可,无论谁去做又怎么做
  • 在函数式编程语言当中Lambda表达式的类型是函数,但在Java8中Lambda表达式是对象而不是函数,它们必须依附于函数式接口

Java内置函数式接口

java.util.function包下定义了Java8的丰富的函数式接口

四大核心函数式接口

函数式接口称谓参数类型用途
Consumer<T> 消费型接口T对类型为T的对象应用操作,包含方法 void accept(T t)
Supplier<T> 供给型接口返回类型为T的对象,包含方法T get()
Function<T, R> 函数型接口T对类型为T的对象应用操作并返回结果R类型的对象,包含方法R apply(T t)
Predicate<T> 判断型接口T确定类型为T的对象是否满足某约束并返回 boolean 值,包含方法boolean test(T t)

消费型接口: 抽象方法有形参但是返回值类型是void

接口名抽象方法描述
BiConsumer<T,U>void accept(T t, U u)接收两个对象用于完成功能
DoubleConsumervoid accept(double value)接收一个double值
IntConsumervoid accept(int value)接收一个int值
LongConsumervoid accept(long value)接收一个long值
ObjDoubleConsumervoid accept(T t, double value)接收一个对象和一个double值
ObjIntConsumervoid accept(T t, int value)接收一个对象和一个int值
ObjLongConsumervoid accept(T t, long value)接收一个对象和一个long值

供给型接口: 抽象方法无参但是有返回值

接口名抽象方法描述
BooleanSupplierboolean getAsBoolean()返回一个boolean值
DoubleSupplierdouble getAsDouble()返回一个double值
IntSupplierint getAsInt()返回一个int值
LongSupplierlong getAsLong()返回一个long值

函数型接口: 抽象方法既有参数又有返回值

接口名抽象方法描述
UnaryOperatorT apply(T t)接收一个T类型对象,返回一个T类型对象结果
DoubleFunctionR apply(double value)接收一个double值,返回一个R类型对象
IntFunctionR apply(int value)接收一个int值,返回一个R类型对象
LongFunctionR apply(long value)接收一个long值,返回一个R类型对象
ToDoubleFunctiondouble applyAsDouble(T value)接收一个T类型对象,返回一个double
ToIntFunctionint applyAsInt(T value)接收一个T类型对象,返回一个int
ToLongFunctionlong applyAsLong(T value)接收一个T类型对象,返回一个long
DoubleToIntFunctionint applyAsInt(double value)接收一个double值,返回一个int结果
DoubleToLongFunctionlong applyAsLong(double value)接收一个double值,返回一个long结果
IntToDoubleFunctiondouble applyAsDouble(int value)接收一个int值,返回一个double结果
IntToLongFunctionlong applyAsLong(int value)接收一个int值,返回一个long结果
LongToDoubleFunctiondouble applyAsDouble(long value)接收一个long值,返回一个double结果
LongToIntFunctionint applyAsInt(long value)接收一个long值,返回一个int结果
DoubleUnaryOperatordouble applyAsDouble(double operand)接收一个double值,返回一个double
IntUnaryOperatorint applyAsInt(int operand)接收一个int值,返回一个int结果
LongUnaryOperatorlong applyAsLong(long operand)接收一个long值,返回一个long结果
BiFunction<T,U,R>R apply(T t, U u)接收一个T类型和一个U类型对象,返回一个R类型对象结果
BinaryOperatorT apply(T t, T u)接收两个T类型对象,返回一个T类型对象结果
ToDoubleBiFunction<T,U>double applyAsDouble(T t, U u)接收一个T类型和一个U类型对象,返回一个double
ToIntBiFunction<T,U>int applyAsInt(T t, U u)接收一个T类型和一个U类型对象,返回一个int
ToLongBiFunction<T,U>long applyAsLong(T t, U u)接收一个T类型和一个U类型对象,返回一个long
DoubleBinaryOperatordouble applyAsDouble(double left, double right)接收两个double值,返回一个double结果
IntBinaryOperatorint applyAsInt(int left, int right)接收两个int值,返回一个int结果
LongBinaryOperatorlong applyAsLong(long left, long right)接收两个long值,返回一个long结果

判断型接口: 抽象方法特点有参但是返回值类型是boolean结果

接口名抽象方法描述
BiPredicate<T,U>boolean test(T t, U u)接收两个对象
DoublePredicateboolean test(double value)接收一个double值
IntPredicateboolean test(int value)接收一个int值
LongPredicateboolean test(long value)接收一个long值

接口的使用

消费型接口使用举例

// 消费性接口
public interface Consumer<Double>{
    void accept (Double money);
}

public void happyTime(double money, Consumer<Double> consumer) {
    // 调用消费型接口的方法
    consumer.accept(money);
}
@Test
public void test04() {
    // 传统写法
    happyTime(1241, new Consumer<Double>() {
        @Override
        public void accept(Double money) {
            System.out.println("突然想回一趟成都了,机票花费" + money);
        }
    });
    System.out.println("------------------------");

    // Lambda表达式
    happyTime(648, money -> System.out.println("学习太累了,奖励自己一发十连,花费" + money));
}

断定型接口使用举例: 根据Predicate接口实现类的实现方法给定的规则,过滤集合中的字符串

public List<String> filterString(List<String> strings, Predicate<String> predicate) {
    ArrayList<String> res = new ArrayList<>();
    for (String string : strings) {
        if (predicate.test(string))
            res.add(string);
    }
    return res;
}

@Test
public void test05() {
    List<String> strings = Arrays.asList("东京", "西京", "南京", "北京", "天津", "中京");
    // 传统写法
    List<String> list = filterString(strings, new Predicate<String>() {
        @Override
        public boolean test(String s) {
            return s.contains("京");
        }
    });
    System.out.println(list);

    System.out.println("------------------------");

    // Lambda表达式
    List<String> res = filterString(strings, s -> s.contains("京"));
    System.out.println(res);
}

Lambda表达式语法的使用

匿名内部类

当需要启动一个线程去完成任务时,通常会通过java.lang.Runnable接口来定义任务内容并使用java.lang.Thread类来启动该线程

  • Thread类需要Runnable接口作为参数,其中的抽象run方法是用来指定线程任务内容的核心
  • 为了指定run的方法体需要创建Runnable接口的实现类,为了省去定义一个RunnableImpl实现类的麻烦需要使用匿名内部类
  • 编写的匿名内部类必须覆盖重写抽象run方法,所以方法名称、方法参数、方法返回值都需要再写一遍且不能写错, 而实际上只有方法体才是关键所在
public class UseFunctionalProgramming {
    public static void main(String[] args) {
        // new 接口(){实现类}
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("多线程任务执行!");
            }
        }).start(); // 启动线程
    }
}

Lambda表达式的6种形式

我们可以通过Lambda表达式创建函数式接口的实现类对象代替匿名实现类,Lambda表达式是用来简化函数式接口的变量或形参赋值的语法

  • 因为函数式接口只有一个抽象方法,所以我们才可以省略方法名称,方法参数,方法返回值,@Override函数声明等内容
new Thread(() -> {
	System.out.println("多线程任务执行!");
}).start(); 

Lambda表达式的语法格式如(o1,o2) -> Integer.compare(o1,o2)

  • ->:lambda操作符或箭头操作符
  • ->左边(函数式接口中抽象方法的形参列表):因为有类型推断机制形参的数据类型都可以省略,如果只有一个参数,参数的小括号可以省略
  • ->右边{函数式接口中抽象方法的方法体}: 当Lambda体只有一条语句时(return语句或其他语句),如果是return语句return与{}需要一起省略, 不能只省略{}return不能单独出现

语法格式一: 函数式接口的抽象方法无参无返回值

@Test
public void test01(){
    // 传统写法
    Runnable runnable01 = new Runnable() {
        @Override
        public void run() {
            System.out.println("你 的 城 市 好 像 不 欢 迎 我");
        }
    };
    runnable01.run();
    System.out.println("-------------------------");
    // Lambda表达式
    Runnable runnable02 = () -> {
        System.out.println("所 以 我 只 好 转 身 离 开 了");
    };
    runnable02.run();
}

语法格式二: 函数式接口的抽象方法有一个参数但是没有返回值

@Test
public void test03(){
    //1. 传统写法
    Consumer<String> consumer01 = new Consumer<String>() {
        @Override
        public void accept(String s) {
            System.out.println(s);
        }
    };
    consumer01.accept("其实我存过你照片 也研究过你的星座");

    System.out.println("-------------------------");
    // Lambda表达式
    Consumer<String> consumer02 = (String s) -> {
        System.out.println(s);
    };
    consumer02.accept("你喜欢的歌我也会去听 你喜欢的事物我也会想去了解");
}

语法格式三: 函数式接口抽象方法中形参列表的数据类型可以省略,编译器可由类型推断机制得出,底层是由声明变量的泛型类型推断得出

在这里插入图片描述

@Test
public void test() {
    //类型推断机制1
    ArrayList<String> list = new ArrayList<>();
    //类型推断机制2
    int[] arr = {1, 2, 3};

}
@Test
public void test04(){
    // 传统写法
    Consumer<String> consumer01 = new Consumer<String>() {
        @Override
        public void accept(String s) {
            System.out.println(s);
        }
    };
    consumer01.accept("我远比表面上更喜欢你");

    System.out.println("-------------------------");
    // Lambda表达式
    Consumer<String> consumer02 = (s) -> {
        System.out.println(s);
    };
    consumer02.accept("但我没有说");
}

语法格式四: 函数式接口的抽象方法只有一个参数,参数的小括号可以省略

@Test
public void test04(){
    // 传统写法
    Consumer<String> consumer01 = new Consumer<String>() {
        @Override
        public void accept(String s) {
            System.out.println(s);
        }
    };
    consumer01.accept("我远比表面上更喜欢你");

    System.out.println("-------------------------");
    // Lambda表达式
    Consumer<String> consumer02 = s -> {
        System.out.println(s);
    };
    consumer02.accept("但我没有说");
}

语法格式五: 函数式接口的抽象方法有两个或以上参数,方法有返回值,方法体有多条执行语句

@Test
public void test02() {
    // 传统的写法
    Comparator<Integer> comparator01 = new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            System.out.println(o1);
            System.out.println(o2);
            return o1.compareTo(o2);
        }
    };
    System.out.println(comparator01.compare(95, 27));
    System.out.println("-------------------------");

    // Lambda表达式
    Comparator<Integer> comparator02 = (o1, o2) -> {
        System.out.println(o1);
        System.out.println(o2);
        return o1.compareTo(o2);
    };
    System.out.println(comparator02.compare(12, 21));
}

语法格式六: 当Lambda体只有一条语句时(可能是return语句),如果是return语句return与{}需要一起省略, 注意不能只省略{}return不能单独出现

public void test02() {
    // 传统写法
    Comparator<Integer> comparator01 = new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return o1.compareTo(o2);
        }
    };
    System.out.println(comparator01.compare(95, 27));
    System.out.println("-------------------------");

    // Lambda表达式
    Comparator<Integer> comparator02 = (o1, o2) -> o1.compareTo(o2);
    System.out.println(comparator02.compare(12, 21));
}

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

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

相关文章

一文详解Vue生命周期

Vue是一种流行的用于构建用户界面的渐进式JavaScript框架。Vue框架在开发过程中&#xff0c;特别强调对生命周期的理解和管理。通过使用生命周期钩子函数&#xff0c;开发者能够精确地控制Vue实例的创建、挂载、更新以及销毁过程。本文将对Vue的生命周期进行详细的介绍&#xf…

航天博物馆3D虚拟交互展厅让大众对科技发展有更深切的理解和感受

博物馆作为人们了解历史、文化和艺术的重要场所&#xff0c;现在可以通过VR全景技术来进行展览&#xff0c;让参观者身临其境地感受历史文化的魅力。本文将介绍博物馆VR全景的特点、优势&#xff0c;以及如何使用VR全景技术来使得博物馆的展览和教育活动更丰富。 VR数字博物馆…

2023年“福建省工业互联网+智能制造创新大赛”开启报名

11月22日&#xff0c;由福建省总工会、福建省大数据集团有限公司共同举办的2023年“福建省工业互联网智能制造创新大赛”启动报名。 大赛积极响应《福建省总工会等八部门关于广泛深入开展劳动和技能竞赛为新发展阶段新福建建设建工立业的意见》&#xff08;闽工〔2022〕70号&am…

String 真的不可变吗?

为什么 String 类不可变 final修饰符&#xff1a; String类被声明为final&#xff0c;这意味着它不能被继承。因此&#xff0c;无法创建String的子类来修改其行为。私有字符数组&#xff08;char[]&#xff09;&#xff1a; String类内部使用私有的字符数组来存储字符串的内容…

最优化理论

最优化理论 资料一optimal condition 最优性条件概念 二一维搜索逐次下降法iterative decent单峰函数二分法 dichotomous search 三 资料 B站最优化理论与算法 上交最优化方法 一 目标函数&#xff1a;需要优化的函数 决策变量&#xff0c;可以调整变化的量 约束集&#xff…

GitHub上8个强烈推荐的 Python 项目

文章目录 前言1. Manim2. DeepFaceLab3. Airflow4. GPT-25. XSStrike6. 谷歌图片下载7. Gensim8. SocialMapper总结关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③…

【Linux】 id命令使用

id id命令来显示用户的UID、组GID。 著者 由阿诺德罗宾斯和大卫麦肯齐撰写。 语法 id [参数] [用户名] id命令 -Linux手册页 命令选项及作用 执行令 id --help 执行命令结果 参数 -g 或 --group  显示用户所属群组的ID。-G 或 --groups  显示用户所属附加群组的ID。…

微信报名怎么做_轻松便捷的数字化报名体验

微信报名&#xff1a;轻松便捷的数字化报名体验 在这个数字化时代&#xff0c;微信已经成为我们生活中不可或缺的一部分。它不仅仅是一个社交平台&#xff0c;更是一个功能强大的综合性工具。其中&#xff0c;微信报名功能更是给我们的生活带来了极大的便利。本文将详细介绍微…

11-23 SSM4

Ajax 同步请求 &#xff1a;全局刷新的方式 -> synchronous请求 客户端发一个请求&#xff0c;服务器响应之后你客户端才能继续后续操作&#xff0c;请求二响应完之后才能发送后续的请求&#xff0c;依次类推 有点&#xff1a;服务器负载较小&#xff0c;但是由于服务器相应…

SpringBoot——启动类的原理

优质博文&#xff1a;IT-BLOG-CN SpringBoot启动类上使用SpringBootApplication注解&#xff0c;该注解是一个组合注解&#xff0c;包含多个其它注解。和类定义SpringApplication.run要揭开SpringBoot的神秘面纱&#xff0c;我们要从这两位开始就可以了。 SpringBootApplicati…

dxva2+ffmpeg硬件解码(Windows)终结发布

《dxva2超低延迟视频播放器》演示demo下载URL&#xff1a; 【免费】dxva2硬解码超低延迟网络本地播放器资源-CSDN文库 本地播放 截图&#xff1a; rtsp播放截图&#xff08;推送内容为本地桌面&#xff0c;所以是这样的&#xff09; OK&#xff0c;进入主题&#xff1a; 前前…

拼多多商品详情数据接口(Pinduoduo.item_get)

拼多多商品详情数据接口是一种程序化的接口&#xff0c;通过这个接口&#xff0c;商家或开发者可以使用自己的编程技能&#xff0c;对拼多多平台上的商品信息进行查询、获取和更新。这个接口允许商家根据自身的需求&#xff0c;获取商品的详细信息&#xff0c;例如价格、库存、…

交通管理中的利器:揭秘交通监控大屏的优势和应用场景

交通监控大屏是一种用于监控交通情况的大屏展示方式&#xff0c;能够实时展示交通状况、车流量、车速等数据&#xff0c;为交通管理提供数据支持和决策参考。本文将介绍交通监控大屏的优势、应用场景和未来发展趋势。 一、交通监控大屏的优势 交通监控大屏的主要优势包括&…

【double check 读写锁】

使用double check 读写锁 读多写少场景 记录下 //来源 jdbc 中的查询连接信息 //public abstract class ConnectionUrl implements DatabaseUrlContainer public static ConnectionUrl getConnectionUrlInstance(String connString, Properties info) {if (connString null…

基于C#实现Prim算法

图论在数据结构中是非常有趣而复杂的&#xff0c;作为 Web 码农的我&#xff0c;在实际开发中一直没有找到它的使用场景&#xff0c;不像树那样的频繁使用&#xff0c;不过还是准备仔细的把图论全部过一遍。 一、最小生成树 图中有一个好玩的东西叫做生成树&#xff0c;就是用…

电脑出现api-ms-win-crt-runtime-l1-1-0.dll丢失的情况有什么解决办法,dll文件丢失的方法

在使用电脑过程中&#xff0c;有时可能会遇到缺失api-ms-win-crt-runtime-l1-1-0.dll文件的问题&#xff0c;这可能导致某些应用程序无法正常运行。本文将介绍三种解决这个问题的方法&#xff0c;并比较它们的优缺点。 一.解决api-ms-win-crt-runtime-l1-1-0.dll丢失的问题 方…

再添千万级罚单,某银行年内罚款过亿!金融行业合规问题亟待解决

11月17日晚间&#xff0c;国家金融监管总局上海监管局披露行政处罚信息显示&#xff0c;某银行因32项违法违规事实收到两张690万元的大额罚单&#xff0c;合计罚款金额达1380万元。但这并不是银行该今年收到的第一张大额罚单。今年4月28日&#xff0c;该行因在结售汇、外币理财…

C语言——接受一个整形值(无符号),使用函数的递归,按照顺序打印他的每一位。

#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>void print(int n) {if(n>9){print(n/10);}printf("%d ",n%10); }int main() {unsigned int num 0;scanf("%d", &num);print(num);return 0; }

【Redis】前言--redis产生的背景以及过程

一.介绍 为什么会出现Redis这个中间件&#xff0c;从原始的磁盘存储到Redis中间又发生了哪些事&#xff0c;下面进入正题 二.发展史 2.1 磁盘存储 最早的时候都是以磁盘进行数据存储&#xff0c;每个磁盘都有一个磁道。每个磁道有很多扇区&#xff0c;一个扇区接近512Byte。…

Colmap三维重建详解与使用方法

图片捕获过程&#xff0c;请遵循以下指导方针以获得最佳重建结果: 1 捕捉具有良好纹理的图像。避免使用完全没有质感的图片(例如&#xff0c;白色的墙或空桌子)。如果场景本身没有足够的纹理&#xff0c;你可以放置额外的背景对象&#xff0c;如海报等。 2 在相似的照明条件下…