函数式编程

news2025/7/29 0:36:55

Lambda表达式介绍

Lambda 简介

 Lambda 表达式是 JDK8 的一个新特性,可以取代大部分的匿名内部类,写出更优雅的 Java 代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代码结构。

在Java语言中,可以为变量赋予一个值:

 能否把一个代码块赋给一变量吗?

 在Java 8之前,这个是做不到的。但是Java 8问世之后,利用Lambda特性,就可以做到了。

 甚至我们可以让语法变得更简洁。

 在Java 8里面,所有的Lambda的类型都是一个接口,而Lambda表达式本身,也就是”那段代码,需要是这个接口的实现。这是我认为理解Lambda的一个关键所在,简而言之就是,Lambda表达式本身就是一个接口的实现。直接这样说可能还是有点让人困扰,我们继续看看例子。我们给上面的aBlockOfCode加上一个类型:

 这种只有一个接口函数需要被实现的接口类型,我们叫它“函数式接口”。为了避免后来的人在这个接口中增加接口函数导致其有多个接口函数需要被实现,变成"非函数接口,我们可以在这个上面加上一个声明@FunctionalInterface, 这样别人就无法在里面添加新的接口函数了。

Lambda作用

最直观的作用就是使得代码变得异常简洁。

 接口要求

虽然使用 Lambda 表达式可以对某些接口进行简单的实现,但并不是所有的接口都可以使用 Lambda 表达式来实现。 Lambda 规定接口中只能有一个需要被实现的方法,不是规定接口中只能有一个方法。
jdk 8 中有另一个新特性: default , 被 default 修饰的方法会有默认实现,不是必须被实现的方法,所以不影响 Lambda 表达式的使用。
@FunctionalInterface 注解作用
@FunctionalInterface 标记在接口上, 函数式接口 是指仅仅只包含一个抽象方法的接口。
Lambda 表达式语法

 

语法结构

(parameters) -> expression
或
(parameters) ->{ statements;}
语法形式为 () -> {}
() 用来描述参数列表,如果有多个参数,参数之间用逗号隔开,如果没有参数,留空即可;
-> 读作 (goes to) ,为 lambda 运算符 ,固定写法,代表指向动作;
{} 代码块,具体要做的事情,也就是方法体内容;
Lambda 表达式的重要特征
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
Lambda 案例
// 1. 不需要参数,返回值为 5  
() -> 5  

// 2. 接收一个参数(数字类型),返回其2倍的值  
x -> 2 * x  

// 3. 接受2个参数(数字),并返回他们的差值  
(x, y) -> x – y  

// 4. 接收2个int型整数,返回他们的和  
(int x, int y) -> x + y  

// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s)


Lambda表达式入门案例

定义函数接口

/**
 * 无返回值,无参数
 */
@FunctionalInterface
interface NoReturnNoParam{
   void method();
}
/**
 * 无返回值,有一个参数
 */
@FunctionalInterface
interface NoReturnOneParam{
   void method(int a);
}
/**
 * 无返回值,有多个参数
 */
@FunctionalInterface
interface NoReturnMultiParam{
   void method(int a,int b);
}
/**
 * 有返回值,无参数
 */
@FunctionalInterface
interface ReturnNoParam{
   int method();
}
/**
 * 有返回值,有一个参数
 */
@FunctionalInterface
interface ReturnOneParam{
   int method(int a);
}
/**
 * 有返回值,有多个参数
 */
@FunctionalInterface
interface ReturnMultiParam{
   int method(int a,int b);
}

实现函数接口

public static void main(String[] args) {
   /**
    * 无返回值,无参数
    */
   NoReturnNoParam noReturnNoParam = ()->{
       System.out.println("NoReturnNoParam");   };
   noReturnNoParam.method();
   /**
    * 无返回值,有一个参数
    */
   NoReturnOneParam noReturnOneParam = (int a)->{
       System.out.println("NoReturnOneParam "+a);
  };
    noReturnOneParam.method(10);
   /**
    * 无返回值,有多个参数
    */
   NoReturnMultiParam noReturnMultiParam = (int a, int b)->{
       System.out.println("NoReturnMultiParam "+a+"\t"+b);
  };
   noReturnMultiParam.method(10,20);
   /**
    * 有返回值,无参数
    */
   ReturnNoParam returnNoParam = ()->{
       System.out.print("ReturnNoParam ");
       return 10;
  };
   System.out.println(returnNoParam.method());
   /**
    * 有返回值,有一个参数
    */
   ReturnOneParam returnOneParam = (int a)->{
       System.out.print("ReturnOneParam ");
       return a;
  };

System.out.println(returnOneParam.method(10));
   /**
    * 有返回值,有多个参数
    */
   ReturnMultiParam returnMultiParam = (int a ,int b)->{
       System.out.print("ReturnMultiParam ");
       return a+b;
  };

System.out.println(returnMultiParam.method(10, 20));
}
Lambda 语法简化
/**
    * 无返回值,无参数
    */
  /* NoReturnNoParam noReturnNoParam = ()->{       
 System.out.println("NoReturnNoParam");
   };*/
   /**
    * 简化版
    */
   NoReturnNoParam noReturnNoParam = ()-> System.out.println("NoReturnNoParam");
   noReturnNoParam.method();
   /**
    * 无返回值,有一个参数
    */
  /* NoReturnOneParam noReturnOneParam = (int a)->{
       System.out.println("NoReturnOneParam "+a);
   };*/
   /**
    * 简化版
    */
   NoReturnOneParam noReturnOneParam = a ->
System.out.println("NoReturnOneParam "+a);
    noReturnOneParam.method(10);
   /**
    * 无返回值,有多个参数
    */
  /* NoReturnMultiParam noReturnMultiParam = (int a, int b)->{
       System.out.println("NoReturnMultiParam "+a+"\t"+b);
   };*/    
     NoReturnMultiParam noReturnMultiParam = (a,b)-> System.out.println("NoReturnMultiParam "+a+"\t"+b);
   noReturnMultiParam.method(10,20);
   /**
    * 有返回值,无参数
    */
  /* ReturnNoParam returnNoParam = ()->{
       System.out.print("ReturnNoParam ");
       return 10;
   };*/
   /**
    * 简化版
    */
   ReturnNoParam returnNoParam = ()->10+20;
   System.out.println(returnNoParam.method());
   /**
    * 有返回值,有一个参数
    */
 /* ReturnOneParam returnOneParam = (int a)->{
       System.out.print("ReturnOneParam ");
       return a;
   };*/
   /***
    * 简化版
    */
   ReturnOneParam returnOneParam = a->a;

System.out.println(returnOneParam.method(10));。
   /**
    * 有返回值,有多个参数
    */
   /*ReturnMultiParam returnMultiParam = (int a ,int b)->{
       System.out.print("ReturnMultiParam ");
       return a+b;
   };*/
   /**
    * 简化版
    */
   ReturnMultiParam returnMultiParam = (a ,b)- >a+b;

System.out.println(returnMultiParam.method(10,20));}

Lambda 表达式的使用
Lambda 表达式引用方法
有时候我们不是必须使用 Lambda 的函数体定义实现,我们可以利用 lambda 表达式指向一个已经存在的方法作为抽象方法的实现。
要求
● 参数的个数以及类型需要与函数接口中的抽象方法一致
● 返回值类型要与函数接口中的抽象方法的返回值类型一致。
语法
方法归属者 :: 方法名 静态方法的归属者为类名,非静态方法归属者为该对象的引用。
案例
/**
 * 无返回值,无参数
 */
@FunctionalInterface
interface NoReturnNoParam{
   void method();
}
/**
 * 无返回值,有一个参数
 */
@FunctionalInterface
interface NoReturnOneParam{
   void method(int a);
}
/**
 * 无返回值,有多个参数
 */
@FunctionalInterface
interface NoReturnMultiParam{
   void method(int a,int b);
}/**
  * 有返回值,无参数
  */
@FunctionalInterface
interface ReturnNoParam{
   int method();
}
/**
 * 有返回值,有一个参数
 */
@FunctionalInterface
interface ReturnOneParam{
   int method(int a);
}
/**
 * 有返回值,有多个参数
 */
@FunctionalInterface
interface ReturnMultiParam{
   int method(int a,int b);
}
public class Test {
   public static void main(String[] args) {
       /**
        * 无返回值,无参数
        */
      /* NoReturnNoParam noReturnNoParam = ()->{
         
System.out.println("NoReturnNoParam");        };*/
       /**
        * 简化版
        */
       NoReturnNoParam noReturnNoParam = ()->
System.out.println("NoReturnNoParam");
       noReturnNoParam.method();
       /**
        * 无返回值,有一个参数
        */
      /* NoReturnOneParam noReturnOneParam = (int a)->{
         
System.out.println("NoReturnOneParam "+a);
       };*/
       /**
        * 简化版
        */
       NoReturnOneParam noReturnOneParam = a - > System.out.println("NoReturnOneParam "+a);
        noReturnOneParam.method(10);
       /**
        * 无返回值,有多个参数
        */
      /* NoReturnMultiParam noReturnMultiParam = (int a, int b)->{
         
System.out.println("NoReturnMultiParam "+a+"\t"+b);
       };*/        NoReturnMultiParam noReturnMultiParam = (a,b)-> System.out.println("NoReturnMultiParam "+a+"\t"+b);
       noReturnMultiParam.method(10,20);
       /**
        * 有返回值,无参数
        */
      /* ReturnNoParam returnNoParam = ()->{
           System.out.print("ReturnNoParam ");
           return 10;
       };*/
       /**
        * 简化版
        */
       ReturnNoParam returnNoParam = ()- >10+20;
     
System.out.println(returnNoParam.method());
       /**
        * 有返回值,有一个参数
        */
     /* ReturnOneParam returnOneParam = (int a)->{
           System.out.print("ReturnOneParam
");
           return a;
       };*/
       /***
        * 简化版
        */        ReturnOneParam returnOneParam = a->a;
     
System.out.println(returnOneParam.method(10));
       /**
        * 有返回值,有多个参数
        */
       /*ReturnMultiParam returnMultiParam = (int a ,int b)->{
           System.out.print("ReturnMultiParam ");
           return a+b;
       };*/
       /**
        * 简化版
        */
       ReturnMultiParam returnMultiParam = (a ,b)->a+b;
     
System.out.println(returnMultiParam.method(10, 20));
  }
   /**
    * 要求:
    * 1,参数的个数以及类型需要与函数接口中的抽象方法一致。
    * 2,返回值类型要与函数接口中的抽象方法的返回值类型一致。
    * @param a
    * @return
    */
   public static int doubleNum(int a){
       return 2*a;
  }
   public int addTwo(int a){
       return a+2;
  }
}
public class Test2 {
   public static void main(String[] args) {
       ReturnOneParam returnOneParam = Test::doubleNum;
       int value = returnOneParam.method(10);
       System.out.println(value);
       Test test = new Test();
       ReturnOneParam returnOneParam1 = test::addTwo;
       int value2 = returnOneParam1.method(10);
       System.out.println(value2);
  }
}

Lambda表达式创建线程

public class Test3 {    public static void main(String[] args) {
     
System.out.println(Thread.currentThread().getName()+" 开始");
       new Thread(()->{
           for(int i=0;i<20;i++){
               try {
                   Thread.sleep(500);
              } catch (InterruptedExceptione) {
                   e.printStackTrace();
              }
             
System.out.println(Thread.currentThread().getName()+" "+i);
          }
      },"Lambda Thread ").start();
     
System.out.println(Thread.currentThread().getName()+" 结束");
  }
}

Lambda 表达式中的闭包问题

什么是闭包
闭包的本质就是代码片断。所以闭包可以理解成一个代码片断的引用。在Java 中匿名内部类也是闭包的一种实现方式。
在闭包中访问外部的变量时,外部变量必须是 final 类型,虚拟机会帮我们加上 final 修饰关键字。
public class Test4 {
   public static void main(String[] args) {
       final int num  =10;
       NoReturnNoParam noReturnNoParam = ()->System.out.println(num);
       noReturnNoParam.method();
  }
}

常用的函数接口

Consumer 接口的使用
Consumer 接口是 JDK 为我们提供的一个函数式接口,该接口也被称为消费型接口。
遍历集合
我们可以调用集合的 public void forEach(Consumer<? super E> action) 方法,通过 lambda 表达式的方式遍历集合中的元素。以下是 Consumer 接口的方法以及遍历集合的操作。
public class Test4 {
   public static void main(String[] args) {
       List<String> list = new ArrayList<>();
       list.add("a");
       list.add("b");
       list.add("c");
       list.add("d");
       list.forEach(System.out::println);
  }
}

Predicate接口的使用

Predicate JDK 为我们提供的一个函数式接口,可以简化程序的编写。
删除集合中的元素
我们通过 public boolean removeIf(Predicate<? super E> filter) 方法来删除集合中的某个元素,
public class Test5 {
   public static void main(String[] args) {
       List<String> list = new ArrayList<>();
       list.add("a");
       list.add("b");
       list.add("c");
       list.add("d");
       list.removeIf(ele->ele.equals("b"));
       list.forEach(System.out::println);
  }
}

Comparator接口的使用

Comparator JDK 为我们提供的一个函数式接口,该接口为比较器接口。
元素排序
之前我们若要为集合内的元素排序,就必须调用 sort 方法,传入比较器重写 compare 方法的比较器对象,现在我们还可以使用lambda 表达式来简化代码。
public class Test7 {
   public static void main(String[] args) {
       List<String> list = new ArrayList<>();
       list.add("a");
       list.add("d");
       list.add("b");
       list.add("c");
       list.sort((o1,o2)->o1.compareTo(o2));
       list.forEach(System.out::println);
  }
}

Stream流介绍

Stream流简介

Stream是数据渠道,用于操作数据源所生成的元素序列,它可以实现对集合的复杂操作,例如过滤、排序和映射等。Stream不会改变源对象,而是返回一个新的结果集。

Stream 流的生成方式
        ● 生成流:通过数据源(集合、数组等)创建一个流。
        ● 中间操作:一个流后面可以跟随零个或者多个中间操作,其目的主要是打开流,做出某种程度的数
        ● 据过滤/映射,然后返回一个新的流,交给下一个操作使用。
        ● 终结操作:一旦执行终止操作,就执行中间的链式操作,并产生结果。
Stream 流的常见方法
数据过滤
public class Test8 {
   public static void main(String[] args) {
       List<String> list = new ArrayList<>();
       list.add("oldlu");
       list.add("oldlin");
       list.add("kevin");
       list.add("peter");
       //多条件and关系
       list.stream().filter(ele ->
ele.startsWith("o")).filter(ele >ele.endsWith("n")).collect(Collectors.toList()
).forEach(System.out::println);
       System.out.println("-------------------
-----");
       //多条件or关系
       Predicate<String> predicate1 = ele ->
ele.startsWith("o");
       Predicate<String> predicate2 = ele-
>ele.endsWith("n");
     
list.stream().filter(predicate1.or(predicate2)
).collect(Collectors.toList()).forEach(System.o
ut::println);
  }
}

数量限制

public class Test9 {
   public static void main(String[] args) {
       List<String> list = new ArrayList<>();
       list.add("oldlu");
       list.add("oldlin");
       list.add("kevin");
       list.add("peter");
       //limit
     
list.stream().limit(2).forEach(System.out::println);
  }
}

元素排序

public class Test10 {
   public static void main(String[] args) {
       List<String> list = new ArrayList<>();
       list.add("b");
       list.add("c");
       list.add("a");
       list.add("d");
       //升序排序
     
list.stream().sorted(Comparator.naturalOrder()).forEach(System.out::println);
       System.out.println("---------------");
       //降序排序
     
list.stream().sorted(Comparator.reverseOrder()).forEach(System.out::println);
  }
}

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

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

相关文章

连续六个季度实现盈利改善,达达集团内外双重确定性凸显

当消费迈向复苏时&#xff0c;今年的社会消费品零售也在总额恢复增长的情况下&#xff0c;迎来结构性变化。 其中&#xff0c;一股消费力量的加速增长成为了重点——即时零售。今年7月&#xff0c;商务部在官网发布的《2022年上半年中国网络零售市场发展报告》&#xff0c;首次…

VOACAP 软件的下载与安装

VOACAP 简介 VOACAP(Voice of America Coverage Analysis Program&#xff0c;美国之音覆盖分析程序)软件是NTIA/ITS开发的高频规划软件包 ITS HF Propagation 中的一个电路计算模块&#xff0c;它是对原 ITS IONCAP 模块(高频传输系统应用预测模块之一)的改进&#xff0c;并根…

LogTAD:无监督跨系统日志异常域检测

摘要 日志异常检测&#xff0c;其对开发稳定、可持续的系统具有重要意义。但当系统刚上线时&#xff0c;收集足够的数据训练一个无监督模型是不现实的。为此本文提出了一个可转移的日志异常检测(LogTAD)框架&#xff0c;该框架利用对抗域适应技术使来自不同系统的日志数据具有…

小程序最新获取用户头像昵称

目录 一、前言 二、遇到的问题 三、效果页面 四、代码实现 记录&#xff1a; 一、前言 昨天打开编辑器后&#xff0c;发现小程序用户的头像与昵称都给变默认了&#xff0c;就去网上搜了一下&#xff1a; 小程序用户头像昵称获取规则调整公告 | 微信开放社区 我去&…

Spring6整合JUnit5

十七、Spring6整合JUnit5 17.1 Spring对JUnit4的支持 准备工作&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instanc…

[附源码]java毕业设计暖暖猫窝系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Linux之软连接和硬连接的用法和区别【详细!!!】

目录软连接创建一个软连接删除软连接硬链接创建硬链接删除硬链接硬链接和软连接之间的区别软连接 创建一个软连接 ln -s [源文件或目录] [软连接名称] 例子&#xff1a; 在/home目录下创建一个软连接linkToRoot 链接到/root目录 删除软连接 rm -f /linkToRoot例子&#x…

供应CAS:73342-16-2,N3-PEG-OH,Azide-PEG-Hydroxy,叠氮-聚乙二醇-羟基

一&#xff1a;产品描述 1、名称 英文&#xff1a;N3-PEG-OH&#xff0c;Azide-PEG-Hydroxy 中文&#xff1a;叠氮-聚乙二醇-羟基 2、CAS编号&#xff1a;73342-16-2 3、所属分类&#xff1a;Azide PEG Hydroxyl PEG 4、分子量&#xff1a;可定制&#xff0c;叠氮-PEG 34…

[附源码]java毕业设计某公司酬薪管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

无需重启应用,动态采集任意点位日志

作者&#xff1a; 屿山 现实系统往往有着较高的复杂度&#xff0c;我们借助 Trace、Log、Metric 三驾马车使我们的系统具备了一定的可观测性&#xff0c;但观测位置和信息往往是固定的&#xff0c;而我们所遇到的问题常常是意料之外的&#xff0c;这就导致我们能够定位问题的范…

BLE学习(1):蓝牙协议栈的介绍

蓝牙官方(The Bluetooth Special Interest Group)定义了低功耗蓝牙(Bluetooth low energy,即LE)和基础/增强速率蓝牙(Bluetooth basic rate/enhanced data rate ,即BR/EDR)两种技术的协议栈。这两种协议栈可以单独使用&#xff0c;也可以同时使用&#xff0c;如下图所示&#x…

泛型「generic」讲解

标题1. 泛型语法1.1 泛型的引出1.2 泛型介绍1.3 泛型语法1.4 泛型使用细节1.5 练习题2.自定义泛型2.1自定义泛型-类2.2自定义泛型-接口2.3自定义泛型-方法2.4练习题3.范型继承和通配符3.1JUnit单元测试框架3.2练习题1. 泛型语法 1.1 泛型的引出 传统方法不能对加入到集合中的…

Docker部署ELK

Docker部署ELK安装包下载1、安装docker2、安装docker compose3、使用docker加载离线镜像4、上传yml文件并初始化密码5、造数据&#xff0c;看采集结果安装包下载 链接:https://pan.baidu.com/s/1LOHyhTHm3-30v6wAfYLTAg 提取码:5uno 1、安装docker &#xff08;1&#xff09…

Python新手的福音,涵盖20+种初学者必练项目!

前言 对学Python的新手同学来说&#xff0c;最最最想要的干货是什么&#xff1f;是大量可以练手的项目啊。俗话说&#xff0c;三天不练手生&#xff0c;三天不念口生。#技术派的书架# &#xff08;文末送读者福利&#xff09; 在某乎上有一个关于"Python的练手项目”的问…

【线程】线程同步

目录 一、信号量 1.函数 2.使用 二、读写锁 1.函数 2.使用 三、互斥锁 1.函数 2.使用 四、条件变量 1.函数 2.使用 前言 线程同步的实现方法&#xff1a;信号量、互斥锁、条件变量、读写锁。 下面就对着四种方法进行展开描述 一、信号量 与进程间通信的信号量类似&a…

JNPF3.4.5大版本正式上线啦!

千呼万唤始出来&#xff0c;时隔近四个月&#xff0c;引迈信息终于再度推出新版本与大家见面了&#xff0c;此次推出的3.4.5大版本&#xff0c;可谓是吊足了大家的胃口。 本次大更新为用户带来的是高效率、高可用性、低成本、快速部署、易于扩展的快速开发平台的使用体验。本次…

【ASM】字节码操作 工具类与常用类 TraceClassVisitor 介绍

文章目录 1.概述2. TraceClassVisitor2.1 class info2.2 字段信息2.3 constructors2.4 methods3.如何使用TraceClassVisitor3.1 生成新的类3.2 修改已有的类3.3 打印ASM信息4.总结感谢第一个订阅字节码的人,感谢老铁支持 adminhjy 1.概述 在上一篇文章:

拓展卡尔曼滤波(Kalman)附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

分享5个良心好用的PC软件,免费无广告

今天再次推荐5个良心好用的Windows神级软件&#xff0c;每一个都是完全免费&#xff0c;堪称神器&#xff0c;让你打开新世界的大门。 1.数据恢复工具——EaseUS Data EaseUS Data Recovery Wizard是一款简单易用的数据恢复工具&#xff0c;给用户提供了三种恢复模式&#xf…

docker部署ES及kibana整个流程

对于ES小白&#xff0c;第一次安装ES走了很多弯路&#xff0c;下面记录自己本地安装elasticsearch的整个过程&#xff0c;我觉得小白如果按照我的流程走&#xff0c;大部分应该可以安装并运行成功。下面是整个步骤&#xff1a; 一、部署ES 拉取镜像 docker pull docker.elast…