一、前言

Java 8 最重要的新特性之一就是函数式编程,而函数式编程的底层根基就是函数式接口
只要吃透 4大核心函数式接口 + 2个高频扩展接口,就能彻底玩转 Lambda 表达式、Stream 流式编程、方法引用,日常开发和面试完全够用。

函数式接口定义:有且仅有一个抽象方法的接口,可使用 @FunctionalInterface 注解标识,支持 Lambda 表达式简化实现。

二、Java 四大核心函数式接口总览

接口名 核心作用 抽象方法 记忆口诀
Supplier<T> 生产者:无参,只返回结果 T get() 只产出、不接收
Consumer<T> 消费者:有参,无返回值 void accept(T t) 只处理、不返回
Function<T, R> 转换器:入参T,出参R R apply(T t) 进T出R、做转换
Predicate<T> 断言判断:入参,返回布尔值 boolean test(T t) 做判断、返真假

三、四大核心接口逐类详解

3.1 Supplier<T> 生产者接口

3.1.1 核心特性

无入参、有返回值,只负责生产对象、生产数据

3.1.2 常用场景

  • 懒加载对象,延迟初始化
  • 生成随机自定义对象
  • 提供默认值

3.1.3 前置实体类

class User {
    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() { return name; }
    public int getAge() { return age; }

    @Override
    public String toString() {
        return name + "-" + age;
    }
}

3.1.4 案例1:生成随机User对象

import java.util.function.Supplier;

public class SupplierDemo {
    public static void main(String[] args) {
        Supplier<User> userSupplier = () ->
                new User("用户" + (int)(Math.random()*100), 18 + (int)(Math.random()*10));

        System.out.println(userSupplier.get());
        System.out.println(userSupplier.get());
    }
}

3.1.5 案例2:懒加载集合对象

import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;

public class SupplierLazyDemo {
    private static final Supplier<Map<String, Object>> mapSupplier = HashMap::new;

    public static void main(String[] args) {
        Map<String, Object> dataMap = mapSupplier.get();
        dataMap.put("name", "张三");
        dataMap.put("age", 22);
        System.out.println(dataMap);
    }
}

3.2 Consumer<T> 消费者接口

3.2.1 核心特性

  • 有入参、无返回值,只负责消费、处理数据。
  • 独有默认方法:andThen(),支持链式拼接多个处理逻辑。

3.2.2 常用场景

  • 集合遍历打印
  • 批量修改对象属性
  • 多段业务逻辑串行执行

3.2.3 案例1:基础用法

import java.util.function.Consumer;

public class ConsumerDemo {
    public static void main(String[] args) {
        Consumer<String> c = str -> System.out.println(str);
        c.accept("我被消费了");
    }
}

3.2.4 案例2:批量修改集合属性

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

public class ConsumerUpdateDemo {
    public static void main(String[] args) {
        List<User> userList = new ArrayList<>();
        userList.add(new User("张三", 17));
        userList.add(new User("李四", 20));

        Consumer<User> updateAge = user -> {
            if (user.getAge() < 18) {
                System.out.println(user.getName() + " 未成年,年龄修正为18");
            }
        };

        userList.forEach(updateAge);
    }
}

3.2.5 案例3:andThen 链式执行

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

public class ConsumerAndThenDemo {
    public static void main(String[] args) {
        List<User> userList = new ArrayList<>();
        userList.add(new User("张三", 17));

        Consumer<User> printUser = System.out::println;
        Consumer<User> renameUser = user -> System.out.println("已实名认证-" + user.getName());

        userList.forEach(printUser.andThen(renameUser));
    }
}

💡 关键点List.forEach() 底层接收的参数就是 Consumer,Lambda 只是简化了函数式接口的实现写法。

3.3 Function<T, R> 转换型接口

3.3.1 核心特性

输入类型 T,输出类型 R,专门用于类型转换、数据映射、数值计算。
独有默认方法:

  • andThen():先执行当前逻辑,再执行后续逻辑
  • compose():先执行传入逻辑,再执行当前逻辑

3.3.2 常用场景

  • 实体类与 DTO 互转
  • Stream 流中 map 映射
  • 多级数据加工处理

3.3.3 案例1:基础转换

import java.util.function.Function;

public class FunctionDemo {
    public static void main(String[] args) {
        Function<String, Integer> f = str -> str.length();
        Integer len = f.apply("hello");
        System.out.println(len);
    }
}

3.3.4 案例2:实体转DTO

class UserDTO {
    private String userName;
    private Integer userAge;

    public UserDTO(String userName, Integer userAge) {
        this.userName = userName;
        this.userAge = userAge;
    }

    @Override
    public String toString() {
        return userName + "," + userAge;
    }
}
import java.util.function.Function;

public class FunctionDtoDemo {
    public static void main(String[] args) {
        Function<User, UserDTO> userToDto = user -> new UserDTO(user.getName(), user.getAge());

        User user = new User("王五", 25);
        UserDTO dto = userToDto.apply(user);
        System.out.println(dto);
    }
}

3.3.5 案例3:链式多级转换

import java.util.function.Function;

public class FunctionChainDemo {
    public static void main(String[] args) {
        Function<String, Integer> strToInt = Integer::valueOf;
        Function<Integer, Integer> addTen = num -> num + 10;

        Function<String, Integer> totalFunc = strToInt.andThen(addTen);
        System.out.println(totalFunc.apply("20"));
    }
}

3.3.6 案例4:Stream 中 map 使用

import java.util.List;

public class FunctionStreamDemo {
    public static void main(String[] args) {
        List<String> list = List.of("a", "b", "c");
        list.stream()
            .map(String::toUpperCase)
            .forEach(System.out::println);
    }
}

3.4 Predicate<T> 判断型接口

3.4.1 核心特性

传入参数,返回 boolean 布尔值,用于条件判断、数据过滤。
独有默认方法:and()or()negate() 可自由组合多条件。

3.4.2 常用场景

  • Stream 流 filter 过滤
  • 业务规则校验
  • 多条件逻辑组合判断

3.4.3 案例1:基础判断

import java.util.function.Predicate;

public class PredicateDemo {
    public static void main(String[] args) {
        Predicate<Integer> p = num -> num > 0;
        boolean b = p.test(10);
        System.out.println(b);
    }
}

3.4.4 案例2:多条件组合过滤

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

public class PredicateFilterDemo {
    public static void main(String[] args) {
        List<User> userList = new ArrayList<>();
        userList.add(new User("张三", 17));
        userList.add(new User("李四", 22));
        userList.add(new User("张无忌", 28));

        Predicate<User> agePredicate = user -> user.getAge() > 18;
        Predicate<User> namePredicate = user -> user.getName().contains("张");

        Predicate<User> finalPredicate = agePredicate.and(namePredicate);

        userList.stream()
                .filter(finalPredicate)
                .forEach(System.out::println);
    }
}

3.4.5 案例3:条件取反、或运算

Predicate<User> notAdult = agePredicate.negate();
Predicate<User> orCond = notAdult.or(user -> user.getName().contains("李"));

四、两大高频扩展函数式接口

4.1 扩展接口总览

接口名 作用 抽象方法
BiConsumer<T,U> 双参数消费者 void accept(T t, U u)
BiFunction<T,U,R> 双参数转换器 R apply(T t, U u)

4.2 BiConsumer<T, U> 双参数消费者

两个入参、无返回值,常用于 Map 遍历、双参数业务处理。

import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;

public class BiConsumerDemo {
    public static void main(String[] args) {
        Map<String, Integer> wordCount = new HashMap<>();
        wordCount.put("java", 10);
        wordCount.put("lambda", 8);

        BiConsumer<String, Integer> printCount = (key, value) ->
                System.out.println("单词:" + key + ",出现次数:" + value);

        wordCount.forEach(printCount);
    }
}

4.3 BiFunction<T, U, R> 双参数转换器

两个入参、一个返回值,常用于数值运算、对象信息合并。

4.3.1 数值平方和运算

import java.util.function.BiFunction;

public class BiFunctionCalcDemo {
    public static void main(String[] args) {
        BiFunction<Integer, Integer, Integer> calc = (a, b) -> a*a + b*b;
        System.out.println(calc.apply(3,4));
    }
}

4.3.2 合并两个用户信息

import java.util.function.BiFunction;

public class BiFunctionMergeDemo {
    public static void main(String[] args) {
        BiFunction<User, User, String> mergeName = (u1, u2) ->
                "合并用户:" + u1.getName() + " & " + u2.getName();

        User u1 = new User("张三", 20);
        User u2 = new User("李四", 22);
        System.out.println(mergeName.apply(u1, u2));
    }
}

五、各接口专属默认方法汇总

接口类型 链式/组合方法 作用
Consumer / BiConsumer andThen() 串行执行多个消费逻辑
Function / BiFunction andThen()compose() 实现多级数据转换
Predicate and()or()negate() 多条件并且、或者、取反
Supplier 无链式拼接方法

六、使用函数式接口的核心好处

  1. 把逻辑当成参数传递:传统开发需手写接口、匿名内部类;现在通过 Lambda 直接传递业务逻辑,代码极度简洁。
  2. 通用模板可复用:框架代码只编写一次,业务逻辑通过函数式接口传入,一套模板适配多种业务场景。
  3. 完美适配 Stream 流式编程:Stream 核心的 filtermapforEach 底层全部依赖函数式接口,代码优雅精简。
  4. 代码松耦合:业务逻辑与框架代码完全分离,修改业务逻辑只需替换 Lambda 表达式,无需改动底层框架。

七、全文总结

  1. 必背四大核心Supplier 生产、Consumer 消费、Function 转换、Predicate 判断
  2. 高频扩展接口BiConsumer 双参消费、BiFunction 双参转换
  3. 链式方法区分Consumer/FunctionandThenPredicateand/or/negate
  4. 核心本质:Lambda 表达式 函数式接口的匿名实现简写,Stream 流底层完全依托函数式接口驱动

更多推荐