函数式编程基本语法

news2024/11/26 17:34:49

文章目录

    • 1.函数对象表现形式
        • 1.Lambda表达式(功能全面)
          • 1.基本语法
          • 2.只有一行逻辑,该逻辑结果是返回值
          • 3.复杂逻辑
          • 4.省略参数类型(可以通过上下文推导出类型时,比如实现了函数式接口)
          • 5.只有一个参数时,参数的圆括号可以省略,但是也不能加参数类型
        • 2.方法引用(写法简洁)
          • 1.类型调用静态方法
          • 2.类型调用成员方法(函数是以对象为基本单位的)
          • 3.对象调用非静态方法
          • 4.类型创建对象
        • 3.练习
          • 1.判断Lambda表达式正确性
          • 2.方法引用转换为Lambda表达式(要素:逻辑,参数,返回值)
          • 3.方法引用实例
        • 4.函数式编程的技巧(重要)
          • 1.定义函数式接口:定义参数 + 返回值
          • 2.Lambda表达式:根据参数和返回值写出逻辑
          • 3.方法引用:根据逻辑反推出参数和返回值
    • 2.函数对象的类型
        • 1.如何归类?
        • 2.归类练习
        • 3.自定义函数式接口
          • 1.函数式接口加上@FunctionalInterface 在编译时检查是否函数式接口有且只有一个抽象方法
          • 2.练习案例
    • 3.JDK提供的函数式接口
        • 1.IntPredicate 参数为int,返回值为boolean
        • 2.IntBinaryOperator 参数为两个int,返回值为int
        • 3.Supplier 参数为空,返回值为泛型
        • 4.Function 参数为泛型,返回值也为泛型
        • 5.实例
        • 6.常见函数接口
          • 1.概览
          • 2.命名规则
        • 7.练习
          • 1.将判断条件使用函数式接口替换 Predicate
            • 1.题目
            • 2.答案
          • 2.一个参数一个返回值 Function
            • 1.题目
            • 2.答案
          • 3.将具体逻辑使用函数式接口替换 Consumer
            • 1.题目
            • 2.结果
          • 4.没有参数,一个返回值 Supplier
            • 1.题目
            • 2.答案
    • 4.方法引用
        • 1.基本介绍
        • 2.六种方法引用的格式
          • 1.类名::静态方法
            • 1.介绍
            • 2.使用lambda表达式的方式,打印所有学生 forEach
            • 3.使用方法引用,打印所有学生 forEach
            • 4.使用lambda表达式的方式,打印所有男学生 filter
            • 5.使用方法引用的方式,打印所有男学生 filter
          • 2.类名:非静态方法
            • 1.介绍
            • 2.使用lambda表达式的方式,打印所有男学生 filter
            • 3.使用方法引用的方式,打印所有男学生 filter
          • 3.对象:非静态方法
            • 1.介绍
            • 2.输出
            • 3.过滤性别是男的
            • 4.将男生转化为女生
          • 4.类名::new
            • 1.介绍
            • 2.调用不同参数个数的构造
          • 5.this::非静态方法和super::非静态方法
            • 1.使用this过滤男性
            • 2.使用super过滤男性
          • 6.六种使用方式对比

1.函数对象表现形式

1.Lambda表达式(功能全面)
1.基本语法
  • 参数 + “->” + {逻辑}
2.只有一行逻辑,该逻辑结果是返回值

image-20240607234452645

3.复杂逻辑

image-20240607234632700

4.省略参数类型(可以通过上下文推导出类型时,比如实现了函数式接口)

image-20240607234756094

5.只有一个参数时,参数的圆括号可以省略,但是也不能加参数类型

image-20240607235117271

2.方法引用(写法简洁)
1.类型调用静态方法

image-20240607235538574

2.类型调用成员方法(函数是以对象为基本单位的)

image-20240607235615587

3.对象调用非静态方法

4.类型创建对象

image-20240608000047017

3.练习
1.判断Lambda表达式正确性

image-20240608000706259

2.方法引用转换为Lambda表达式(要素:逻辑,参数,返回值)

image-20240608001236212

3.方法引用实例

image-20240608001643179

4.函数式编程的技巧(重要)
1.定义函数式接口:定义参数 + 返回值
2.Lambda表达式:根据参数和返回值写出逻辑
3.方法引用:根据逻辑反推出参数和返回值

2.函数对象的类型

1.如何归类?

image-20240608001755717

2.归类练习

image-20240608001939742

3.自定义函数式接口
1.函数式接口加上@FunctionalInterface 在编译时检查是否函数式接口有且只有一个抽象方法
package com.sun.first;

/**
 * @Author sun
 * @Create 2024/6/7 22:51
 * @Version 1.0
 */
public class Sample2 {

    public static void main(String[] args) {
        // 参数和返回值需要与函数对象一致
        Fun fun = (a) -> {
            return a + 1;
        };
        System.out.println(fun.test(2));
    }
}

// 在编译时检查是否函数式接口有且只有一个抽象方法
@FunctionalInterface
interface Fun {
    int test(int a);
}
2.练习案例
package com.sun.first;

import java.util.ArrayList;

/**
 * @Author sun
 * @Create 2024/6/7 22:51
 * @Version 1.0
 */
public class Sample2 {

    public static void main(String[] args) {
        // 参数和返回值需要与函数对象一致
        Fun fun = (a) -> {
            return a + 1;
        };
        System.out.println(fun.test(2));

        Fun1 fun1 = (int a, int b, int c) -> a + b + c;

        Fun2 fun2 = (int a, int b) -> a - b;

        Fun3 fun3 = () -> new String();

        Fun4 fun4 = () -> new ArrayList<String>();

        Fun5<String, Integer> fun5 = (str) -> {
            return Integer.valueOf(str);
        };

        System.out.println(fun5.test("34"));
    }
}

// 在编译时检查是否函数式接口有且只有一个抽象方法
@FunctionalInterface
interface Fun {
    int test(int a);
}

@FunctionalInterface
interface Fun1 {
    int test(int a, int b, int c);
}

@FunctionalInterface
interface Fun2 {
    int test(int a, int b);
}

@FunctionalInterface
interface Fun3 {
    String test();
}

@FunctionalInterface
interface Fun4 {
    ArrayList<String> test();
}

// 参数和返回值都是泛型
@FunctionalInterface
interface Fun5<I, O> {
    O test(I input);
}



3.JDK提供的函数式接口

1.IntPredicate 参数为int,返回值为boolean

image-20240608211325083

2.IntBinaryOperator 参数为两个int,返回值为int

image-20240608211706550

3.Supplier 参数为空,返回值为泛型

image-20240608212044668

4.Function 参数为泛型,返回值也为泛型

image-20240608211951855

5.实例

image-20240608212058797

6.常见函数接口
1.概览

image-20240608212149243

2.命名规则

image-20240608212831086

7.练习
1.将判断条件使用函数式接口替换 Predicate
1.题目

image-20240608213428171

2.答案
package com.sun.first;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

/**
 * Description: 将判断条件使用函数式接口替换
 * @Author sun
 * @Create 2024/6/8 21:35
 * @Version 1.0
 */
public class Sample4 {
    public static void main(String[] args) {
        List<Integer> filter = filter(Arrays.asList(1, 2, 3), i -> {
            // 这里的参数是Integer类型的,返回值是boolean类型,逻辑是判断i是否是偶数,当然也可以更换
            return (i & 1) == 0;
        });
        System.out.println("filter = " + filter);
    }

    // 过滤一下list,得到list中的偶数
    static List<Integer> filter(List<Integer> list, Predicate<Integer> predicate) {
        // 使用一个List来存储结果
        List<Integer> res = new ArrayList<>();
        // 过滤出偶数
        for (Integer i : list) {
            // 其中当i的最后一位是1的时候&1才是1,否则为0,也就是偶数
            // 这里的函数式接口的意思就是,参数为i,返回值为boolean,也就是如果结果是true,才进行添加
            if (predicate.test(i)) {
                res.add(i);
            }
        }
        return res;
    }
}
2.一个参数一个返回值 Function
1.题目

image-20240608215636309

2.答案
package com.sun.first;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;

/**
 * Description:
 * @Author sun
 * @Create 2024/6/8 21:57
 * @Version 1.0
 */
public class Sample5 {
    public static void main(String[] args) {
        List<String> map = map(Arrays.asList(1, 2, 3), a -> {
            return String.valueOf(a);
        } );
        System.out.println(map);
    }

    static List<String> map(List<Integer> list, Function<Integer, String> function) {
        List<String> res = new ArrayList<>();
        for (Integer i : list) {
            // 将结果转换为String类型
            // 将具体逻辑使用函数式接口替换,参数为Integer类型的i,返回值为String类型,使用Function
            res.add(function.apply(i));
        }
        return res;
    }
}
3.将具体逻辑使用函数式接口替换 Consumer
1.题目

image-20240608221111329

2.结果
package com.sun.first;

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

/**
 * Description:
 * @Author sun
 * @Create 2024/6/8 22:14
 * @Version 1.0
 */
public class Sample6 {
    public static void main(String[] args) {
        consume(Arrays.asList(1, 3, 3), num -> {
            System.out.println("num = " + num);
        });

    }

    static void consume(List<Integer> list, Consumer<Integer> consumer) {
        for(Integer num : list) {
            // 打印,但是以后逻辑可能改变
            // 一个参数,为Integer类型的num,没有返回值,使用Consumer
            consumer.accept(num);
        }
    }
}
4.没有参数,一个返回值 Supplier
1.题目

image-20240608222201277

2.答案
package com.sun.first;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.Supplier;

/**
 * Description:
 * @Author sun
 * @Create 2024/6/8 22:22
 * @Version 1.0
 */
public class Sample7 {
    public static void main(String[] args) {
        List<Integer> supply = supply(3, () -> {
            // 逻辑为生成一个随机数
            int res = ThreadLocalRandom.current().nextInt();
            System.out.println(res);
            return res;
        });
    }

    static List<Integer> supply(int count, Supplier<Integer> supplier) {
        List<Integer> result = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            // 生成随机数,但是逻辑可能改变
            // 参数为空,返回值为一个,使用Supplier
            result.add(supplier.get());
        }
        return result;
    }
}

4.方法引用

1.基本介绍

2.六种方法引用的格式
1.类名::静态方法
1.介绍

image-20240610211507579

2.使用lambda表达式的方式,打印所有学生 forEach
package com.sun.methodref;

import java.util.stream.Stream;

/**
 * Description:
 * @Author sun
 * @Create 2024/6/10 21:19
 * @Version 1.0
 */
public class MethodRef01 {
    public static void main(String[] args) {
        Stream.of(
                new Student("libai", "男"),
                new Student("dufu", "男"),
                new Student("lishimin", "女")
        ).forEach(student -> {
            // 挑选出所有的男的
                System.out.println(student);
        });
    }
}

class Student {
    private String name;
    private String sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Student(String name, String sex) {
        this.name = name;
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                '}';
    }
}
3.使用方法引用,打印所有学生 forEach
public class MethodRef01 {
    public static void main(String[] args) {
        Stream.of(
                new Student("libai", "男"),
                new Student("dufu", "男"),
                new Student("lishimin", "女")
        ).forEach(MethodRef01::abc);
        // 对于forEach来说,参数为每个元素,返回值为空
        // 所以无论是lambda表达式还是方法引用,他们都遵循这个条件:(Student stu) -> void
    }

    public static void abc(Student student) {
        System.out.println(student);
    }
}
4.使用lambda表达式的方式,打印所有男学生 filter
    public static void main(String[] args) {
        Stream.of(
                        new Student("libai", "男"),
                        new Student("dufu", "男"),
                        new Student("lishimin", "女")
                ).filter(student -> {
                    // (Student student) -> boolean
                    if (student.getSex().equals("男")) {
                        return true;
                    }
                    return false;
                })
                .forEach(MethodRef01::abc);
    }

    public static void abc(Student student) {
        System.out.println(student);
    }
}
5.使用方法引用的方式,打印所有男学生 filter
public static void main(String[] args) {
    Stream.of(
                    new Student("libai", "男"),
                    new Student("dufu", "男"),
                    new Student("lishimin", "女")
            ).filter(MethodRef01::filter).
            forEach(MethodRef01::abc);
}

// (Student student) -> boolean
public static boolean filter(Student student) {
    return student.getSex().equals("男");
}


public static void abc(Student student) {
    System.out.println(student);
}
2.类名:非静态方法
1.介绍

image-20240610214942622

2.使用lambda表达式的方式,打印所有男学生 filter
public static void main(String[] args) {
    Stream.of(
                    new Student("libai", "男"),
                    new Student("dufu", "男"),
                    new Student("lishimin", "女")
            ).filter(student -> {
                // 使用lambda表达式
                return student.isMale(student);
            })
            .forEach(MethodRef01::abc);
}

image-20240610215931898

3.使用方法引用的方式,打印所有男学生 filter
public void main(String[] args) {
    Stream.of(
                    new Student("libai", "男"),
                    new Student("dufu", "男"),
                    new Student("lishimin", "女")
            ).filter(Student::isMale)
            .forEach(MethodRef01::abc);
}

image-20240610215931898

3.对象:非静态方法
1.介绍

image-20240616211647151

2.输出

image-20240616212406632

3.过滤性别是男的

image-20240616213001113

4.将男生转化为女生

image-20240616213655158

4.类名::new
1.介绍

image-20240616214029702

2.调用不同参数个数的构造
package com.sun.first;

import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * Description:
 * @Author sun
 * @Create 2024/6/16 21:42
 * @Version 1.0
 */
public class Sample9 {

    public static void main(String[] args) {
        // 调用无参构造
        Supplier<Student> m1 = Student::new;
        Student student = m1.get();
        System.out.println("student = " + student);
        // 调用一个参数的构造
        Function<String, Student> m2 = Student::new;
        Student sun = m2.apply("sun");
        System.out.println("sun = " + sun);
        // 调用两个参数的构造
        BiFunction<String, String, Student> m3 = Student::new;
        Student apply = m3.apply("sun", "男");
        System.out.println("apply = " + apply);
    }
}
5.this::非静态方法和super::非静态方法
1.使用this过滤男性
package com.sun.first;

import java.util.stream.Stream;

/**
 * Description:
 * @Author sun
 * @Create 2024/6/17 21:18
 * @Version 1.0
 */
public class Sample10 {

    /**
     * 判断学生是否是男的
     * @param student
     * @return
     */
    Boolean isMan(Student student) {
        return student.getSex().equals("男");
    }

    public void main(String[] args) {
        Stream.of(
                // 三个Student对象
                new Student("libai", "男"),
                new Student("dufu", "男"),
                new Student("lishimin", "女")
        ).filter(this::isMan);
    }

}
2.使用super过滤男性

image-20240617212527690

6.六种使用方式对比

image-20240617213827064

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

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

相关文章

SQL160 国庆期间每类视频点赞量和转发量

描述 用户-视频互动表tb_user_video_log iduidvideo_idstart_timeend_timeif_followif_likeif_retweetcomment_id110120012021-09-24 10:00:002021-09-24 10:00:20110NULL210520022021-09-25 11:00:002021-09-25 11:00:30001NULL310220022021-09-25 11:00:002021-09-25 11:00…

【数据结构】红黑树实现详解

在本篇博客中&#xff0c;作者将会带领你使用C来实现一棵红黑树&#xff0c;此红黑树的实现是基于二叉搜索树和AVLTree一块来讲的&#xff0c;所以在看本篇博客之前&#xff0c;你可以先看看下面这两篇博客 【C】二叉搜索树-CSDN博客 【数据结构】AVLTree实现详解-CSDN博客 在这…

21.FuturePromise

在异步处理时,经常用到两个接口Future 和 Promise。 说明:Netty中的Future与jdk中的Future同名,但是是两个接口,netty的Future继承了jdk的Future,而Promise又对Netty的Future进行了扩展。 JDK的Future只能同步等待任务结束(成功、失败)才能得到结果。FutureTask.get()方…

项目(一)--高并发内存池项目简介

什么是高并发内存池 它是一个全球性大厂google(谷歌)的 开源项目,项目名字叫tcmalloc,全称是Thread-Caching Malloc,即线程缓存的malloc 作用&#xff1a; 我们知道C语言在堆上开辟空间和 释放使用的是malloc和free函数 并且C的动态内存管理new和delete 的底层实际上也调用了…

高考志愿填报:选择好专业还是好学校?

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 高考志愿填报&#xff1a;选择好专业还是好学校&#xff1f; 每年高考结束后&#xff0c;考生和家长面临的一个…

数据结构之线性表(3)

数据结构之线性表&#xff08;3&#xff09; 上文我们了解了线性表的静动态存储的相关操作&#xff0c;此篇我们对线性表中链表的相关操作探讨。 在进行链表的相关操作时&#xff0c;我们先来理解单链表是什么&#xff1f; 1.链表的概念及结构 链表是一种物理存储结构上非连…

密钥管理简介

首先我们要知道什么是密钥管理&#xff1f; 密钥管理是一种涉及生成、存储、使用和更新密钥的过程。 密钥的种类 我们知道&#xff0c;对称密码主要包括分组密码和序列密码。但有时也可以将杂凑函数和消息认证码划分为这一类&#xff0c;将它们的密钥称为对称密钥&#xff1b;…

RAG与Langchain简介

RAG与Langchain简介 什么是RAGRAG解决的问题RAG工作流程RAG调优策略LangChain简介 什么是RAG 检索增强生成&#xff08;Retrieval-Augmented Generation&#xff09;&#xff0c;主要是通过从外部给大模型补充一些知识&#xff0c;相当于给模型外挂了一个知识库&#xff0c;让…

Navicat 安装及初步配置指南

Navicat 是一款广泛使用的数据库管理工具&#xff0c;支持多种数据库&#xff0c;如 MySQL、PostgreSQL、SQLite 等。以下是 Navicat 安装步骤的详细说明&#xff1a; 在 Windows 上安装 Navicat 下载 Navicat 安装包&#xff1a; 访问 Navicat 官方网站&#xff1a;Navicat 官…

iCopy for Mac 剪切板 粘贴工具 历史记录 安装(保姆级教程,新手小白轻松上手)

Mac分享吧 文章目录 效果可留存文本、图片、文件等复制历史记录也可根据关键字进行历史记录检索点击一下&#xff0c;可复制双击两下&#xff0c;复制内容&#xff0c;并将信息粘贴至鼠标指针处 一、准备工作二、开始安装1、双击运行软件&#xff0c;将其从左侧拖入右侧文件夹…

【Vue】Pinia管理用户数据

Pinia管理用户数据 基本思想&#xff1a;Pinia负责用户数据相关的state和action&#xff0c;组件中只负责触发action函数并传递参数 步骤1&#xff1a;创建userStore 1-创建store/userStore.js import { loginAPI } from /apis/user export const useUserStore defineStore(…

Havoc工具

Team端 客户端 打开后需要生成监听器和agent 监听 生成payload 最后上线 HTTPS流量 HTTP流量 心跳

基于微信小程序的在线答题小程序设计与实现

个人介绍 hello hello~ &#xff0c;这里是 code袁~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的…

安装 Nuxt.js 的步骤和注意事项

title: 安装 Nuxt.js 的步骤和注意事项 date: 2024/6/17 updated: 2024/6/17 author: cmdragon excerpt: Nuxt.js在Vue.js基础上提供的服务器端渲染框架优势&#xff0c;包括提高开发效率、代码维护性和应用性能。指南详细说明了从环境准备、Nuxt.js安装配置到进阶部署技巧&…

大模型KV Cache节省神器MLA学习笔记(包含推理时的矩阵吸收分析)

首先&#xff0c;本文回顾了MHA的计算方式以及KV Cache的原理&#xff0c;然后深入到了DeepSeek V2的MLA的原理介绍&#xff0c;同时对MLA节省的KV Cache比例做了详细的计算解读。接着&#xff0c;带着对原理的理解理清了HuggingFace MLA的全部实现&#xff0c;每行代码都去对应…

dentacare - hackmyvm

简介 靶机名称&#xff1a;dentacare 难度&#xff1a;中等 靶场地址&#xff1a;https://hackmyvm.eu/machines/machine.php?vmdentacare 本地环境 虚拟机&#xff1a;vitual box 靶场IP&#xff08;dentacare&#xff09;&#xff1a;192.168.56.120 跳板机IP(window…

使用Multipass编译OpenHarmony工程

Multipass 是一个轻量级虚拟机管理器&#xff0c;支持 Linux、Windows 与 macOS&#xff0c;这是为希望使用单个命令提供全新 Ubuntu 环境的开发人员而设计的。使用 Linux 上的 KVM、Windows 上的 Hyper-V 和 macOS 上的 HyperKit 来以最小的开销运行 VM&#xff0c;同时它还可…

驱动开发(二):创建字符设备驱动

往期文章&#xff1a; 驱动开发&#xff08;一&#xff09;&#xff1a;驱动代码的基本框架 驱动开发&#xff08;二&#xff09;&#xff1a;创建字符设备驱动 ←本文 驱动开发&#xff08;三&#xff09;&#xff1a;内核层控制硬件层 目录 字符驱动设备的作用 函数 …

找不到vcomp100.dll无法继续执行代码的原因及解决方法

在日常使用电脑的过程中&#xff0c;我们可能会遇到一些错误提示&#xff0c;其中之一就是“vcomp100.dll丢失”。那么&#xff0c;vcomp100.dll是什么&#xff1f;它为什么会丢失&#xff1f;对电脑有什么具体影响&#xff1f;如何解决这个问题&#xff1f;本文将为您详细解答…

SpringBoot整合SpringDataRedis

目录 1.导入Maven坐标 2.配置相关的数据源 3.编写配置类 4.通过RedisTemplate对象操作Redis SpringBoot整合Redis有很多种&#xff0c;这里使用的是Spring Data Redis。接下来就springboot整合springDataRedis步骤做一个详细介绍。 1.导入Maven坐标 首先&#xff0c;需要导…