关注CodingTechWork

引言

  Java 8 引入了 函数式编程(Functional Programming) 范式,极大地简化了代码结构,提升了可读性和可维护性。  
其中,java.util.function 包是函数式编程的核心,它定义了大量函数式接口,使得我们可以使用 Lambda 表达式方法引用 来传递行为。

本文将重点剖析其中最常用的四大接口:

接口名功能描述抽象方法
Consumer<T>接收参数,无返回值(消费型)void accept(T t)
Supplier<T>无参数,返回结果(供给型)T get()
Predicate<T>接收参数,返回布尔值(断言型)boolean test(T t)
Function<T,R>接收参数,返回结果(函数型)R apply(T t)

接口详解与源码分析

Consumer:数据消费者

定义与特点

  • 作用:接收一个参数并执行某种操作,无返回值
  • 典型用途:打印日志、修改对象状态、遍历集合。

源码结构

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);

    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

示例:打印字符串列表

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

public class ConsumerExample {
    public static void main(String[] args) {
        Consumer<String> printer = System.out::println;

        List.of("Alice", "Bob", "Charlie").forEach(printer);
    }
}

使用场景

  • 日志记录
  • 集合遍历(如 forEach
  • 对象状态修改(如设置属性)

Supplier:数据提供者

定义与特点

  • 作用无输入参数,但返回一个值。
  • 典型用途:延迟计算、生成默认值、提供工厂对象。

源码结构

@FunctionalInterface
public interface Supplier<T> {
    T get();
}

示例:生成随机数

import java.util.function.Supplier;
import java.util.Random;

public class SupplierExample {
    public static void main(String[] args) {
        Supplier<Integer> randomSupplier = () -> new Random().nextInt(100);
        System.out.println("Random: " + randomSupplier.get());
    }
}

使用场景

  • 延迟初始化(如 Optional.orElseGet(Supplier)
  • 工厂模式(如 () -> new Object()
  • 提供配置值或常量

Predicate:条件判断器

定义与特点

  • 作用:接收一个参数,返回 boolean 值。
  • 典型用途:过滤、校验、条件判断。

源码结构

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);

    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}

示例:过滤空字符串

import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class PredicateExample {
    public static void main(String[] args) {
        Predicate<String> notEmpty = s -> !s.isEmpty();

        List<String> list = List.of("A", "", "B", "  ", "C");
        List<String> filtered = list.stream()
                                    .filter(notEmpty)
                                    .collect(Collectors.toList());
       // [A, B,   , C]
        System.out.println(filtered); 
    }
}

使用场景

  • 数据过滤(如 Stream.filter
  • 参数校验
  • 条件分支逻辑

Function:类型转换器

定义与特点

  • 作用:接收一个参数,返回一个结果,支持类型转换。
  • 典型用途:数据映射、类型转换、提取字段。

源码结构

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

示例:字符串转整数

import java.util.function.Function;

public class FunctionExample {
    public static void main(String[] args) {
        Function<String, Integer> strToInt = Integer::valueOf;

        Integer result = strToInt.apply("123");
        // 124
        System.out.println(result + 1); 
    }
}

使用场景

  • 数据转换(如 DTO → VO)
  • 字段提取(如 User::getName
  • 链式处理(如 composeandThen

接口对比总结

接口输入输出功能描述典型方法
Consumer消费数据accept(T t)
Supplier提供数据get()
Predicate✅(boolean)条件判断test(T t)
Function类型转换apply(T t)

组合使用四大接口

import java.util.*;
import java.util.function.*;

public class CombineExample {
    public static void main(String[] args) {
        Supplier<List<String>> supplier = () -> List.of("apple", "banana", "pear", "grape");

        Predicate<String> startsWithA = s -> s.startsWith("a");
        Function<String, String> toUpper = String::toUpperCase;
        Consumer<String> printer = System.out::println;

        supplier.get().stream()
                .filter(startsWithA)
                .map(toUpper)
                .forEach(printer);
    }
}

输出:

APPLE

如何优雅地使用这些接口?

建议说明
✅ 优先使用 Lambda简化匿名内部类写法
✅ 使用方法引用System.out::println
✅ 组合链式调用andThencompose
✅ 自定义函数式接口使用 @FunctionalInterface 注解

参考资料

更多推荐