Java 8的变革:函数式编程和Lambda表达式探索
创始人
2024-11-03 23:09:28
0

在这里插入图片描述

文章目录

    • 一、函数接口
    • 二、Lambda表达式简介
    • 三、Lambda表达式外部参数
    • 四、Lambda范例
    • 五、Runnable Lambda表达式

一、函数接口

函数接口是一个具有单个抽象方法的接口,接口设计主要是为了支持 Lambda 表达式和方法引用,使得 Java 能更方便地实现函数式编程风格。

特点和用途:

  1. 单一抽象方法: 函数接口只能有一个抽象方法,但可以有多个默认方法(default)或静态方法(static)。
  2. Lambda 表达式: 可以使用函数接口创建 Lambda 表达式,从而简洁地表示匿名函数,例如在集合操作、线程处理等场景中。
  3. 方法引用: 可以通过函数接口的类型来引用一个已存在的方法,使代码更简洁和可读性更高。

Java 8 提供了几个标准的函数接口,接口通常位于 java.util.function 包中。

常见的函数接口:

  • Consumer: 接收一个输入参数并且不返回结果的操作。

    Consumer printConsumer = str -> System.out.println(str); printConsumer.accept("Hello World!"); 
  • Supplier: 不接收参数但是返回结果的提供型接口。

    Supplier randomSupplier = () -> Math.random(); System.out.println(randomSupplier.get()); 
  • Function: 接收一个输入参数,并返回结果。

    Function intToString = num -> String.valueOf(num); System.out.println(intToString.apply(123)); 
  • Predicate: 接收一个输入参数,并返回一个布尔值结果。

    Predicate isEven = num -> num % 2 == 0; System.out.println(isEven.test(5)); // false 
  • UnaryOperator: 继承自 Function,表示一元操作符。

    UnaryOperator square = num -> num * num; System.out.println(square.apply(5)); // 25 

自定义函数接口:只需确保接口中只有一个抽象方法即可。

@FunctionalInterface interface MyFunctionalInterface {     void myMethod();     // 允许有默认方法和静态方法     default void anotherMethod() {         System.out.println("Default method");     } }  // 使用自定义的函数接口 MyFunctionalInterface myFunc = () -> System.out.println("Hello Custom Functional Interface"); myFunc.myMethod(); myFunc.anotherMethod(); 

二、Lambda表达式简介

Lambda 表达式可以被视为匿名函数的一种声明方式,允许将函数作为方法参数传递,或者在需要函数式接口的地方使用。

基本结构:

// parameters:参数列表,可以为空或非空 // ->:箭头符号,分隔参数列表和Lambda表达式的主体 // expression:单行表达式作为 Lambda 主体 (parameters) -> expression  // { statements; }:代码块作为 Lambda 主体,可以包含多条语句和返回语句 (parameters) -> { statements; } 

表达式的特点:

  1. 简洁性和可读性: Lambda 表达式使代码更为简洁,尤其是在处理函数式接口时,省去了冗余的语法。
  2. 函数式编程风格: Lambda 表达式支持函数式编程,可以轻松地进行函数传递、方法引用和流式操作等。
  3. 闭包性: Lambda 表达式可以捕获其周围的变量,使得函数式编程中的状态管理更加灵活。

案例:通过 Lambda 表达式为 MathOperation 接口的 operation 方法提供了四种不同的实现:加法、减法、乘法和除法。

  1. 接口的定义:
interface MathOperation {     int operation(int a, int b); } 
  1. 使用 Lambda 表达式来实现这个接口,以便传递不同的数学运算逻辑:
public class LambdaDemo {     public static void main(String[] args) {         // Lambda 表达式实现加法         MathOperation addition = (int a, int b) -> a + b;         System.out.println("10 + 5 = " + operate(10, 5, addition));          // Lambda 表达式实现减法         MathOperation subtraction = (a, b) -> a - b;         System.out.println("10 - 5 = " + operate(10, 5, subtraction));          // Lambda 表达式实现乘法         MathOperation multiplication = (int a, int b) -> { return a * b; };         System.out.println("10 * 5 = " + operate(10, 5, multiplication));          // Lambda 表达式实现除法         MathOperation division = (a, b) -> a / b;         System.out.println("10 / 5 = " + operate(10, 5, division));     }      private static int operate(int a, int b, MathOperation mathOperation) {         return mathOperation.operation(a, b);     } } 

三、Lambda表达式外部参数

Lambda 表达式有自己特定的作用域规则,可以捕获和访问其周围的变量, 可以随意引用外部变量,但如果外部变量是在当前作用域声明的,则一定不可以进行第二次赋值,哪怕是在 lambda 语句之后。

  1. 局部变量:Lambda 表达式可以访问它们所在方法的局部变量,但是这些变量必须是隐式最终或实际上是最终的(final)。这意味着变量一旦赋值后不再改变。Lambda 表达式内部不允许修改这些局部变量的值,否则编译器会报错。

    public class LambdaScopeDemo {     public static void main(String[] args) {         int num = 10; // 局部变量         MathOperation addition = (int a, int b) -> {             // num = 5; // 错误!Lambda 表达式不能修改局部变量的值             // 这里访问了局部变量 num             return a + b + num;         };         System.out.println(addition.operation(5, 3));     } } 
  2. 字段:Lambda 表达式可以访问外部类的字段(成员变量),包括实例字段和静态字段。

    public class LambdaScopeDemo {     private static int staticNum; // 静态字段      private int instanceNum; // 实例字段      public void testLambdaScope() {         MathOperation addition = (int a, int b) -> {             // 访问实例字段和静态字段             int result = a + b + instanceNum + staticNum;             return result;         };         System.out.println(addition.operation(5, 3));     } } 
  3. 接口的默认方法:Lambda 表达式可以访问接口中定义的默认方法,但不能访问接口中定义的实例字段。

四、Lambda范例

使用Lambda表达式时,常见的场景包括对集合的遍历、排序、过滤以及与函数式接口的结合使用。

常见的Java 8 Lambda表达式示例

  1. 遍历集合
public static void main(String[] args) {         List names = new ArrayList<>();         names.add("Alice");         names.add("Bob");         names.add("Charlie");          // 使用 Lambda 表达式遍历集合         names.forEach(name -> System.out.println(name));     } 
  1. 使用函数式接口进行计算

参考二、Lambda表达式简介

  1. 使用函数式接口进行条件过滤
public static void main(String[] args) {         List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);          // 使用 Lambda 表达式过滤偶数         System.out.println("偶数:");         filter(numbers, n -> n % 2 == 0);          // 使用 Lambda 表达式过滤大于 5 的数         System.out.println("大于 5 的数:");         filter(numbers, n -> n > 5);     }      private static void filter(List numbers, Predicate condition) {         for (Integer number : numbers) {             if (condition.test(number)) {                 System.out.print(number + " ");             }         }         System.out.println();     } 
  1. 使用Comparator进行集合排序
public static void main(String[] args) {         List names = new ArrayList<>();         names.add("Alice");         names.add("Bob");         names.add("Charlie");          // 使用 Lambda 表达式进行排序(根据字符串长度)         names.sort((s1, s2) -> s1.length() - s2.length());          // 输出排序后的结果         names.forEach(name -> System.out.println(name));     } 
  1. 使用 Runnable 执行代码块

参考五、Runnable Lambda表达式

五、Runnable Lambda表达式

使用 Lambda 表达式来简洁地实现 Runnable 接口的实例化。Runnable 接口是一个函数接口,它只包含一个抽象方法 void run(),用于定义一个可以由线程执行的任务。

  1. 匿名内部类(Java 7 及之前):
Runnable runnable = new Runnable() {     @Override     public void run() {         System.out.println("Running in a separate thread");     } };  Thread thread = new Thread(runnable); thread.start(); 
  1. Lambda 表达式(Java 8+)
Runnable runnable = () -> {     System.out.println("Running in a separate thread"); };  Thread thread = new Thread(runnable); thread.start(); 
  1. 更简洁的方式:任务非常简单,可以进一步简化,直接将 Lambda 表达式作为参数传递给 Thread 的构造函数:
Thread thread = new Thread(() -> {     System.out.println("Running in a separate thread"); }); thread.start(); 

这种方式避免了显式地声明 Runnable 变量,使代码更加紧凑和易读。

案例:

public static void main(String[] args) {         // 使用 Lambda 表达式创建一个新的线程         Thread thread = new Thread(() -> {             for (int i = 0; i < 5; i++) {                 System.out.println("线程执行:" + i);                 try {                     Thread.sleep(1000);                 } catch (InterruptedException e) {                     e.printStackTrace();                 }             }         });          // 启动线程         thread.start();     } 

莫道君行早,更有早行人

相关内容

热门资讯

科技实测!斗牛房间怎么创建的老... 微信游戏中心:老神兽/皇豪互众房卡在哪里买打开微信,添加客服微信【88355042】,进入游戏中心或...
IA解析/牛牛房卡出售新鸿狐大... 新鸿狐大厅/随意玩是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:【3329006910】或QQ:3...
秒懂教程!微信怎么开牛牛房间,... 牛牛是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:66336574许多玩家在游戏中会购买房卡来享受...
IA解析/牛牛房卡官网光明联盟... IA解析/牛牛房卡官网光明联盟/房卡最便宜的中心Sa9Ix苹果iPhone 17手机即将进入量产阶段...
一分钟推荐“微信链接金花房卡怎... 新荣耀是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:160470940许多玩家在游戏中会购买房卡来...
重大通报,牛牛房卡出售星驰娱乐... 您好!微信星驰娱乐大厅链接获取房卡可以通过以下几种方式购买: 1.微信渠道:(星驰娱乐)大厅介绍:...
秒懂教程!微信群牛牛房间买房卡... 牛牛是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:56001354许多玩家在游戏中会购买房卡来享受...
秒懂教程“牛牛链接房卡找谁购买... 新永和是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:15984933许多玩家在游戏中会购买房卡来享...
正版授权!游戏推荐斗牛房卡出售... 您好!微信超稳众娱大厅链接获取房卡可以通过以下几种方式购买: 1.微信渠道:(超稳众娱)大厅介绍:...
秒懂教程!炸金花房卡链接在哪买... 炸金花是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:71319951许多玩家在游戏中会购买房卡来享...
秒懂教程“微信斗牛房卡怎么买”... 微信斗牛是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:160470940许多玩家在游戏中会购买房卡...
玩家攻略,牛牛房卡制作链接九尾... 微信游戏中心:九尾大厅房卡在哪里买打开微信,添加客服微信【88355042】,进入游戏中心或相关小程...
秒懂教程!微信牛牛房卡专卖店联... 斗牛是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:66336574许多玩家在游戏中会购买房卡来享受...
终于找到“开牛牛群怎么买房卡”... 牛牛是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:44346008许多玩家在游戏中会购买房卡来享受...
一分钟了解!金花房卡官网九天大... 一分钟了解!金花房卡官网九天大厅/房卡购买批发价格Sa9Ix苹果iPhone 17手机即将进入量产阶...
头条推荐!怎么买斗牛房卡火星大... 您好!微信火星大厅/新道游大厅链接获取房卡可以通过以下几种方式购买: 1.微信渠道:(火星大厅/新...
重大通报,游戏推荐斗牛房卡出售... 今 日消息,泡泡娱乐房卡添加微信33549083 苹果今日发布了 iOS 16.1 正式版更新,简单...
秒懂教程!玩拼三张房卡从哪里买... 拼三张是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:56001354许多玩家在游戏中会购买房卡来享...
终于找到“微信群金花房卡哪里可... 人皇大厅是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:160470940许多玩家在游戏中会购买房卡...
推荐一款!游戏推荐牛牛房卡出售... 久久大厅房卡更多详情添加微:33549083、 2、在商城页面中选择房卡选项。 3、根...