Java 函数式编程(Lambda)

jdk8开始新增

函数式编程: 使用Lambda函数替代某些匿名内部类对象,从而让程序代码更简洁,可读性更好


7.1 Lambda函数简介

可以用于替代某些匿名内部类对象,从而让程序更简洁,可读性更好

复制代码
(被重写方法的形参列表) -> {
      被重写方法的方法体代码  
}

注意 : Lambda表达式只能替代函数式接口的匿名内部类!

!什么是函数式接口?

有且仅有一个抽象方法的接口

注意:将来我们见到的大部分函数式接口,上面都可能会有一个@FunctionalInterface的注解,该注解用于约束当前接口必须是函数式接口

示例:

java 复制代码
// 1. 定义一个函数式接口(有且仅有一个抽象方法)
@FunctionalInterface
interface Calculator {
    int add(int a, int b);
}

public class LambdaBasicDemo {
    public static void main(String[] args) {
        // 【传统写法】匿名内部类
        Calculator oldWay = new Calculator() {
            @Override
            public int add(int a, int b) {
                return a + b;
            }
        };

        // 【Lambda写法】简洁明了
        Calculator lambdaWay = (int a, int b) -> {
            return a + b;
        };

        System.out.println(lambdaWay.add(3, 5)); // 输出: 8
    }
}

7.2 Lambda表达式的省略规则

作用:用于进一步简化Lambda表达式的写法

具体规则:

  1. 参数类型全部可以省略不写
  2. 如果只有一个参数,参数类型省略的同时"()"也可以省略,但多个参数不能省略"()"
  3. 如果Lambda表达式中只有一行代码,大括号可以不写,同时要省略分号";"如果这行代码是return语句,也必须去掉return

示例:

java 复制代码
import java.util.Arrays;
import java.util.List;

public class LambdaOmissionDemo {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

        // 【完整写法】
        // names.forEach((String name) -> { System.out.println(name); });

        // 【省略规则演示】
        // 1. 省略参数类型 String
        // 2. 只有一个参数,省略小括号 ()
        // 3. 只有一行代码,省略大括号 {}、分号 ; 
        names.forEach(name -> System.out.println(name));
    }
}

7.3 方法引用

进一步简化 Lambda 表达式

以下4中特定场景才能用方法引用

7.3.1 静态方法引用

格式:类名::静态方法

使用场景:如果某个Lambda表达式里只是调用一个静态方法,并且"→"前后参数的形式一致,就可以使用静态方法引用

示例:

java 复制代码
import java.util.Arrays;
import java.util.List;

public class StaticMethodRefDemo {
    // 自定义静态方法,参数与Consumer.accept(T)一致
    public static void printUpperCase(String s) {
        System.out.println(s.toUpperCase());
    }

    public static void main(String[] args) {
        List<String> list = Arrays.asList("hello", "world");

        // Lambda写法: list.forEach(s -> StaticMethodRefDemo.printUpperCase(s));
        // 静态方法引用: 前后参数形式一致,直接引用
        list.forEach(StaticMethodRefDemo::printUpperCase);
    }
}
7.3.2 实例方法引用

格式:对象名::实例方法

使用场景:如果某个Lambda表达式里只是通过对象名称调用一个实例方法,并且"→"前后参数的形式一致,就可以使用实例方法引用

示例:

java 复制代码
import java.util.Arrays;
import java.util.List;

public class InstanceMethodRefDemo {
    public void printWithPrefix(String s) {
        System.out.println(">> " + s);
    }

    public static void main(String[] args) {
        InstanceMethodRefDemo obj = new InstanceMethodRefDemo();
        List<String> list = Arrays.asList("Java", "Lambda");

        // Lambda写法: list.forEach(s -> obj.printWithPrefix(s));
        // 实例方法引用: 通过已有对象调用实例方法
        list.forEach(obj::printWithPrefix);
    }
}
7.3.3 特定类的方法引用

格式:特定类的名称::方法

使用场景:如果某个Lambda表达式里只是调用一个特定类型的实例方法,并且前面参数列表中的第一个参数是作为方法的主调,后面的所有参数都是作为该实例方法的入参的,则此时就可以使用特定类型的方法引用

示例:

java 复制代码
import java.util.Arrays;
import java.util.List;

public class ClassMethodRefDemo {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("hello", "WORLD", "Java");

        // Lambda写法: list.forEach(s -> s.toLowerCase())
        // 这里 s 是第一个参数,同时也是 toLowerCase() 的调用者
        // 符合"特定类的方法引用"场景
        list.forEach(String::toLowerCase); 
        
        // 注意:上面这行只是演示语法,实际forEach需要Consumer
        // 更常见的实际使用场景是在Stream中:
        list.stream()
            .map(String::toUpperCase)  // s -> s.toUpperCase()
            .forEach(System.out::println);
    }
}
7.3.4 构造器引用

格式:类名::new

使用场景:如果某个Lambda表达式里只是在创建对象,并且"→"前后参数情况一致,就可以使用构造器引用

示例:

java 复制代码
import java.util.function.Function;
import java.util.function.Supplier;

class User {
    private String name;
    
    // 无参构造
    public User() { this.name = "Default"; }
    
    // 有参构造
    public User(String name) { this.name = name; }
    
    @Override
    public String toString() { return "User{name='" + name + "'}"; }
}

public class ConstructorRefDemo {
    public static void main(String[] args) {
        // 【无参构造器引用】 对应 Supplier<User>
        // Lambda: () -> new User()
        Supplier<User> userSupplier = User::new;
        System.out.println(userSupplier.get()); // User{name='Default'}

        // 【有参构造器引用】 对应 Function<String, User>
        // Lambda: name -> new User(name)
        Function<String, User> userFunction = User::new;
        System.out.println(userFunction.apply("张三")); // User{name='张三'}
    }
}

相关推荐
2601_9637491041 分钟前
越华环保集团数字化污水治理:端边云采集架构与平台对接实现
java·大数据·架构
xcLeigh1 小时前
Go入门:整数类型的溢出与安全边界
java·安全·golang
LorryJovens1 小时前
【LAAP科研】CEN因果等价网络理论---从双缝干涉到因果等价
开发语言·php
源码宝2 小时前
SpringBoot+Vue2 诊所门诊管理系统,完整前后端源码,可直接部署上线
java·源码·his系统·门诊系统·程序代码·诊所系统·门诊his
yychen_java2 小时前
九:Text-to-SQL 智能数据查询与 Human-in-the-Loop 人机协作
java·人工智能·架构
Brilliantwxx2 小时前
【Linux】 进程(10) 进程控制深度解析:创建、终止与等待
linux·运维·服务器·c语言·开发语言·网络
lhldsg3 小时前
智慧场馆解决方案小程序开发实战:从架构设计到部署指南
java·小程序·uni-app
卢锡荣3 小时前
国产PD3.1全集成Type-C管控芯片LDR6020P
c语言·开发语言
Freak嵌入式3 小时前
Pico UART 数据收发实战:硬件配置、MicroPython 编程
java·开发语言·单片机·嵌入式硬件·生活
Casual3 小时前
【网络基础进阶】:看懂子网划分与 VLAN
开发语言·网络·php