神奇的Lambda表达式-----函数式编程

Java泛型与Lambda表达式:函数式编程的完美结合 在Java编程的世界里,我们总是希望能够用更高效、更简洁的方式来实现功能。Java泛型和Lambda表达式就是两个强大的工具,它们能让我们的代码变得更加灵活和优雅。本文的目的就是深入探讨这两者是如何在函数式编程中完美结合的,范围涵盖了从基本概念的解释到实际应用的案例分析。本文首先会介绍核心概念,用有趣的故事引出Java泛型和Lambda表达式,然后详细解释它们的原理和相互关系。接着会阐述核心算法原理和具体操作步骤,给出相关的数学模型和公式。之后通过项目实战,展示代码的实际案例并进行详细解释。 阅读详情

在这里插入图片描述
Lambda表达式是jdk1.8出现的一种重要的新特性,它允许将函数作为参数进行传递(函数式编程),能够极大的简洁代码。点击查看Oracle官网有关于jdk8的新特性描述。

以最常见到的使用Runnable创建线程为例。
使用匿名内部类创建:

Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("do something here");
            }
        },"thread");

使用lambda表达式的形式创建:

Thread thread = new Thread(() -> System.out.println("do something here"), "thread");

可以说代码的数量减少很多,看起来也很简洁。

Lambda

简单的语法

参数 -> 表达式
args -> experssion

Lambda表达式特征

  1. 可选的类型声明:编译器可以通过上下文来推到类型
  2. 可选的参数括号:如果只有一个参数,可以不定义括号
  3. 可选的大括号:如果函数体只有一条语句,可以省略大括号
  4. 可选的返回关键字:如果主体只有一个表达式返回值,则编译器会自动返回值

简单举例

1、不需要参数: () -> 5
2、接受一个参数: x -> x+5
3、接收两个参数: (x,y) -> x-y
4、接收int类型参数:(int a, int b) -> x+y
5、接收参数,返回空: (String s) -> System.out.println(s);

应用场景

Lambda表达式适合应用在任何有函数式接口的地方

什么是函数式接口?

简单来说就是只有一个抽象方法的接口,从API的形式来看就是具有@FunctionalInterface注解的接口。关于注解可以看我之前的文章点击查看。

那么这里强调函数式接口是具有一个抽象方法的接口。不是所有接口的方法都是抽象的么?事实上接口可以声明Object类中的方法,比如toString,equals方法。比如下面这种情况是可以的:@FunctionalInterface interface Test { void say(); String toString(); }
而且,在jdk8以后,接口中可以添加default方法,这也不是一个抽象方法。你可以通过查看Comparator接口定义来分辨。

常见的函数式接口

java.util.function包下存在很多的函数式接口,适用于不同场景。
在这里插入图片描述
这里就不一一介绍了,下面如果在某个举例中用到再进行详细说明。

方法引用

  方法引用是用来直接访问类或者实例的已经存在的方法或者构造方法,方法引用提供了一种引用而不执行方法的方式,如果抽象
方法的实现恰好可以使用调用另外一个方法来实现,就有可能可
以使用方法引用。

分类

  • 静态方法引用:如果函数式接口的实现恰好可以通过调用一个静态方法来实现,那么就可以使用静态方法引用
    格式:Class::staticMethod
  • 实例方法引用:如果函数式接口的实现恰好可以通过调用一个实例的实例方法来实现,那么就可以使用实例方法引用
    格式:Class::instanceMethod
  • 对象方法引用:抽象方法的第一个参数类型刚好是实例方法的类型,抽象方法剩余的参数恰好可以当做实例方法的参数。如果函数式接口的实现能由上面说的实例方法调用来实现的话,那么就可以使用对象方法引用
    格式:object::instanceMethod
  • 构造方法引用:如果函数式接口的实现恰好可以通过调用一个类的构造方法来实现,那么就可以使用构造方法引用
    格式:Class::new

使用

静态方法引用
class TT {
    public static String fun2() {
        System.out.println("tt   --   fun2");
        return "fun2";
    }
}

下面分别是以方法引用的形式和lambda语法形式来执行。

public static void main(String[] args) {
        Supplier<String> fun2 = TT::fun2;
        System.out.println(fun2.get());

		Supplier<String> supplier = () -> TT.fun2();
        System.out.println(supplier.get());
}

这里提到了Supplier,它是一个函数式接口。

Supplier< T > 没有参数,返回类型为T,通过get方法来执行获取返回值。

实例方法引用
class TT {
     public void fun(String a) {
        System.out.println("tt"+a+"   --   fun");
    }
}
public static void main(String[] args) {
        Consumer<String> consumer = a -> new TT().fun(a);
        consumer.accept("0");

        Consumer<String> consumer1 = new TT()::fun;
        consumer.accept("1");
    }

这里用到了Consumer函数接口。

Consumer< T >接口是一个参数类型为T,没有返回值的函数接口。通过accept方法来传入参数并执行。

对象方法引用
public static void main(String[] args) {

        Comparator<String> comparator = (a, b) -> a.compareToIgnoreCase(b);
        int compare1 = comparator.compare("a", "b");
        System.out.println(compare1);

        Comparator<String> compare = String::compareToIgnoreCase;
        int i = compare.compare("a", "b");
        System.out.println(i);

    }

Comparator接口大家应该很熟悉了,这里就不多赘述。

那么静态方法和对象方法两者的区别在哪里?
对象方法会将第一个参数作为方法的目标。只需要记住这样一个例子即可:String::compareToIgnoreCase,
那么以Lambda形式来写的话就是
(a, b) -> a.compareToIgnoreCase(b)

构造方法引用
class Acc {

    public Acc() {
        System.out.println("无参构造");
    }

    public Acc(int a) {
        System.out.println("有参构造"+a);
    }
    
}
    public static void main(String[] args) {
        Supplier<Acc> s2 = Acc::new;
        s2.get();

        Consumer<Integer> c1 = Acc::new;
        c1.accept(234);

        Function<Integer,Acc> f1 = Acc::new;
        Acc apply = f1.apply(234444);

    }

这里提到了Function。

Function<T,R> ,其中T为参数,R为返回值。通过apply方法传入参数并返回

为什么用Lambda

  lambda最重要的一点是延迟执行,毕竟如果要立即执行代码的话,完全没有必要写再lambda表达式中。上面代码中使用静态引用的方式:

Supplier<String> fun2 = TT::fun2;

这一句话其实是没有执行fun2函数的,大家可以尝试一下。

为什么延迟执行

  1. 在一个单独线程中运行代码。
  2. 需要多次运行
  3. 在适当的时候执行代码
  4. 在某种情况下执行代码(比如触发器)

比如输出n个数,使用lambda的方式可以这样写:

public static void repeat(int i, IntConsumer intConsumer) {
        System.out.println("repeat");
        for (int j = 0; j < i; j++) {
            intConsumer.accept(j);
        }
}

调用:

repeat(10, i -> System.out.println(9 - i));

例子

集合的迭代:

    public static void main(String[] args) {
        List<String> list = Arrays.asList("a,b,c,d".split(","));
        list.forEach(System.out::println);
        
    }

排序:

 public static void main(String[] args) {
            String[] array = {"a", "ff", "ab", "cd", "rwdfsd", "abc"};
            //Arrays.sort(array, (a, b) -> a.length() - b.length());
            Arrays.sort(array, Comparator.comparingInt(String::length));
            System.out.println(Arrays.asList(array));
}

参考文章:《Java核心技术卷1》


毕业的事情基本告一段落了,对自己的校招进行了一些总结和梳理。现在在终于能够静下心来分享一些知识了,希望能够帮到大家!

如果有哪些不足和错误,欢迎大家指出~

在这里插入图片描述

Java中的Lambda表达式与函数式编程:为什么它们让你的代码更简洁优雅? 哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛 阅读详情

相关推荐

DDR内存设计必看:DFI接口协议详解与实战避坑指南(附时序图解析)

本文深入解析了DDR内存设计中连接内存控制器与物理层的DFI接口协议,聚焦于DDR4/DDR5设计的实际痛点。文章详细阐述了协议版本兼容性、时钟架构(匹配频率与频率比系统)、PCB信号完整性设计以及上电初始化与调试等关键环节,为硬件工程师提供了一套从理论到实战的完整避坑指南,并附有时序图解析以助理解。

weixin_29256771的博客 329

计算机语言lambda,神奇的lambda表达式——函数式编程必学

作为一名有追求的程序员,对于计算机基础的理论一定要有所了解。最近几年,随着分布式、云计算等技术的发展,函数式编程语言也趋于流行。如果要学习函数式编程,一定要深入理解它背后的理论知识。从收益的角度上讲,这些基础理论知识几十年不变,是十分值得花时间进行学习的。lambda演算(Lambda Calcus)就属于这样一套理论,可以说它在函数式编程领域就如牛顿万有引力定律一样基础。接下来这篇文章我将主要介...

weixin_35106801的博客 1075

Zephyr,设备树概述

Zephyr使用设备树(DTS)描述硬件配置,通过设备树源码和绑定文件生成C头文件供开发使用。设备树采用树状结构,节点对应硬件设备,属性描述硬件特性。示例展示了I2C总线及其外设的节点层级关系,包括单元地址、兼容性标识等关键属性。构建系统将设备树转换为devicetree.h中的宏,使开发者能通过DT_前缀宏访问硬件信息,同时保留Kconfig覆盖默认值的能力。

汽车电子软件领域知识分享 720

java必须了解的函数式编程及lambda表达式

什么是函数式编程 在介绍函数式编程前,先了解一下平时我们所使用命令式编程,命令式编程是告诉计算机如何一步一步执行编程风格。 比如我们要在一个苹果的对象集合中筛选出颜色为红色的苹果集合。我们需要写以下代码: 创建存储苹果的集合list 遍历这个集合 判断苹果颜色是不是为红色,如果满足条件,加入结果集合 public static List&amp;amp;amp;lt;Apple&amp;amp;amp;gt; getRedAppleDecl...

清风的Blog 2287

TBtools的序列提取步骤

本教程详细介绍了如何使用TBtools软件从原来的FASTA序列中提取特定的DNA序列。

weixin_47509995的博客 1万+

cadence——MOS晶体管I-V特性曲线仿真

MOS晶体管I-V特性曲线仿真 目标:使用cadence绘制晶体管的I-V特性曲线(dc仿真) 流程: 新建原理图,将MOS管的栅极电压设为变量Vg,漏极电压设为变量Vd 打开ADEL,点击Variables——Copy From Cellview添加变量;并选择dc仿真,对Vd进行扫描 以Vg作为参变量进行仿真,点击Tools——Parametric Analysis进行设置 选择漏极电流作为输出,进行仿真即可得到I-V特性曲线 ...

skycmq的博客 1万+

函数式编程/lambda表达式

一.命令式编程与函数式编程的区别 1.命令式编程 命令式编程:需要告诉程序所有的编程细节 public class demo{ public static void main(String[] args) { int[] nums = {33,44,55,-666,90}; int min = Integer.MAX_VALUE; for...

Jack汪喆的技术分享栏 702

Unity Sprite Editor切片功能详解:如何快速将一张大图拆分成多个小图(附常见问题解决)

本文详细解析了Unity Sprite Editor的切片功能,指导开发者如何高效地将一张大图拆分为多个独立小图。文章涵盖了自动与手动切片操作步骤、轴心点设置、子精灵命名管理等核心技巧,并针对切片错位、性能优化等常见问题提供了实用解决方案,帮助提升2D游戏资源处理效率。

i0j1k2l3m的博客 646

Java-策略设计模式-lambda表达式的函数式编程实现

1.引子  最近学习了一定的Java并发编程,想试着实现类似于Thread类(lambda表达式作为参数)的构造器实现,想了解其中的设计模式,即策略设计模式,而查阅资料,发现许多文章并非是从类的设计角度出发,并且很多没有将Java8的函数式编程纳入其中,故作此文。 2.设计模式思路  明确目标:我们所要达到的目的是,使用对象构造器的时候直接可以将lambda表达式传入构造器,而不用对每个对象中的父...

li_xunhuan的博客 454

AgentScope实战训练营:从零搭建一个完整的A2A Agent应用

2024年4月,Google在Google Cloud Next大会上正式提出了A2A(Agent-to-Agent)协议,这是一个开放协议,旨在让不同的AI Agent之间能够像微服务一样相互发现、相互调用。通俗地讲:A2A协议就是AI Agent世界的HTTP协议——有了它,一个Agent可以把自己的能力以标准化的方式暴露出去,另一个Agent可以无缝地发现并调用它。本文将基于阿里巴巴开源的(Apache 2.0协议),手把手带你从零搭建一个完整的A2A Agent应用。

program哲学 561

YOLOv8多传感器融合技术——毫米波雷达融合技术详解

本文介绍了YOLOv8与毫米波雷达融合技术在自动驾驶系统中的应用。毫米波雷达具有全天候工作、测距测速精准等优势,但存在分辨率低等局限。通过融合YOLOv8的视觉检测能力,可显著提升系统在恶劣环境下的感知性能。文章详细阐述了融合实现方法,包括雷达数据处理、目标投影匹配、置信度融合等关键技术,并提供了评估指标和应用场景分析。这种多传感器融合方案能有效弥补单一传感器的不足,为自动驾驶提供更可靠的环境感知能力,是实现高级别自动驾驶的重要技术支撑。

u010117029的博客 174

总结之Lambda表达式与函数式编程

Lambd表达式 范例:传统的面向对象开发 interface IMessage2{ void print(); } public class TestDemo { public static void main(String[] args) { IMessage2 message2 = new IMessage2() {//匿名内部类 @...

老司机开车啦 288

Python爬虫博客:如何抓取时事新闻信息 —— 从各大新闻网站获取实时新闻数据

发送请求:向目标新闻网站发送 HTTP 请求,获取网页内容。解析网页:使用解析库(如)从网页中提取新闻标题、摘要、内容、发布时间等。绕过反爬虫机制:使用代理、设置请求头、模拟浏览器行为等策略绕过反爬虫技术。数据存储与清洗:将抓取的数据保存到本地文件或数据库中,并进行清洗,确保数据的可用性。在抓取过程中,我们还会面对很多实际问题,比如反爬虫技术、分页抓取、动态加载的内容等。接下来,我们将逐步介绍如何使用不同技术抓取静态和动态网页,并对抓取的内容进行处理。Scrapy。

2201_76125261的博客 2130

带你彻底掌握 Lambda 表达式(上)

更多技术文章,欢迎关注我的微信公众号:码不停蹄的小鼠松(微信号:busy_squirrel),也可扫下方二维码关注获取最新文章哦~ 说明: 由于 Lambda 表达式涉及的周边知识点实在太多,因此拆分为上、下两篇文章讲解,本篇为上篇,下篇随后放出,大家可在我公众号中查找。 目录介绍: 上篇,主要讲 1~4 章节,下篇,主要介绍 5~8 章节。 序言 JDK8 日渐成为项目开发中的主流。...

tianzhihensu的专栏 2848

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Java8函数式编程之二 : Lambda表达式

针对上篇博客最后留下的问题,也就是java8怎样解决匿名内部类代码难看,臃肿的的问题

zlz18225318697的博客 421

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Lambda表达式

尽管使用了策略模式,上面的代码还是有问题。当然,我们还可以从另一个角度理解:Java8的Lambda都是基于上下文推导的,当一个接口只有一个方法时,推导结果是唯一确定的,但是方法不唯一时,无法推导得到唯一结果。什么是方法引用,我们后面再介绍,可以单纯地理解为可复用的Lambda(把其他类已经定义的方法作为Lambda),实际开发时依靠IDEA提示改进即可,并不需要我们记忆。嗯,没错,到此为止这大概是JDK8之前我们能想到的最好的解决办法,不仅运用了策略模式,还使用匿名类的方式成功阻止了类的暴增。

smart_an的专栏 1084

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

lambda表达式的使用

神奇的lambda表达式 在jdk1.8中新增加了lambda表达式,可能有的小伙伴在github上面学习别人的项目的时候会看到有这样的符号 -> 一个箭头类似于JS中的箭头函数,很神奇吧,这个就是jdk8中新增的lambda表达式。 为什么我们要使用lambda表达式 有的小伙伴可能会问为什么我们要使用lambda表达式,lambda表达式采用的是函数式编程,无需关心如何实现,并且代码非...

技术无止境 5402

What?Java这么神奇的lambda表达式

目录: 1.面向对象的思想和函数式编程思想的概述 2.解决冗余的Runnable代码问题 3.Lambda标准格式及使用 1.面向对象的思想和函数式编程思想的概述 面向对象的思想:找一个能解决事情的对象,然后靠调用对象的方法解决事情 函数式编程的思想:只要能获取到结果,谁做的怎么做的都不重要,只重视结果不重视过程 2.解决冗余的Runnable代码问题 1.冗余的Runnable代码问题...

记录博主学到的点滴 421

Java8——函数式编程

Java8——函数式编程 一、引入 函数式编程语言操纵代码片段就像操作数据一样容易。 虽然 Java 不是函数式语言,但 Java 8 Lambda 表达式和方法引用 (Method References) 允许你以函数式编程。 首先,创建一个名为Talk的接口,接口中只有一个抽象方法,方法名为say public interface Talk { String say(); } 然后创建一个测试类来创建该接口的实例,在之前都习惯于某个类继承该接口,然后创建该类的实例或者是使用匿名内部类的

仲景的博客 1179

《C++新潮流:巧用 Lambda 表达式开启函数式编程之旅》

在 C++的编程世界中,Lambda 表达式的出现犹如一颗璀璨的新星,为开发者带来了全新的编程体验和强大的功能。总之,Lambda 表达式为 C++的函数式编程带来了新的活力和可能性。让我们紧跟编程潮流,充分发挥 Lambda 表达式的神奇魔法,开启精彩的函数式编程之旅。Lambda 表达式,也被称为匿名函数,是一种可以在代码中直接定义和使用的小型函数。因此,在性能敏感的代码中,要谨慎使用 Lambda 表达式,并进行性能测试。如果需要捕获外部变量,要确保捕获的方式是正确的,避免出现意外的结果。

xy520521的博客 582

[转]Java Lambda表达式初探

Java Lambda表达式初探 Java Lambda表达式初探 前言 本文受启发于Trisha Gee在JavaOne 2016的主题演讲Refactoring to Java 8。 Java 8已经发行两年多,但很多人仍然在使用JDK7。对企业来说,技术上谨慎未必是坏事,但对个人学习而言,不去学习新技术就很可能被技术抛弃。Java 8一个重要的变更是引入Lambda表达式

满脑子灵感的专栏 1043

C++11 Lambda 表达式

1.简介 定义: C++11新增了很多特性,lambda表达式(lambda expression)就是其中之一,很多语言都提供了 lambda 表达式,如 Python,Java ,C#等。本质上, lambda 表达式就是一个可调用的代码单元[1]^{[1]}。 作用: 以往C++需要传入一个函数的时候,必须事先进行声明,视情况可以声明为一个普通函数然后传入函数指针,或者声明一个仿函数...

Doublelv 的博客专栏。 3971

函数式编程概述

在Java中如何像JS一样把代码片段/函数当做参数来传递?看Java 8的函数式编程

liudun_cool的博客 489

关于JAVA8的Lambda表达式

Lambda 表达式本质上是一个函数,它是可以作为一个一个参数传给另一个函数使用,而这个参数的类型是函数式接口。只有一个抽象方法的接口就叫函数式接口。

zhenye1986的专栏 1137

Java中lambda表达式的使用

从结果截图可以看出,我们成功实现了LambdaFunction 接口中的getInit() 方法,但是没有定义实现类,使用一行代码就实现了一个接口,是不是很神奇!调用方法:有一个入参name ,所以我们在使用lambda表达式时,需要把入参方法()中,并且在使用这个方法时,需要填写入参,本例:入参为 "同学"表达式,是java8出现的新特性,它是函数式编程的一种体现,使得程序看起来更加整洁。结合上面的语法,表达的抽象接口没有入参,括号内不填参数,为 ();实现方法:本例抽象方法有返回值,使用时别忘获取;

NeverNeverGiveUp的博客 489

lambda表达式java_Lambda表达式Java教程

lambda表达式java 在本文中,我们提供了全面的Lambda Expressions Java教程。 1. Lambda Expressions Java教程–简介 Lambda表达式被认为是Java 8中引入的最好的功能之一。Lambda表达式被认为是Java进入函数式编程世界的第一步 。 可以将其视为无需类即可创建的函数。 它也可以像参数一样传递,并且可以在需要时和根据需要执行。...

最佳 Java 编程 164
上一篇: Java高级技巧之注解(Annotation)
下一篇: 关于租房的一点小小感触和建议
mechanic-heaven
博客等级 码龄9年 8粉丝 40原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值