教程中心 / Java教程 / 常用函数式接口

常用函数式接口

18分钟 函数式编程

引言:什么是函数式接口?

函数式接口(Functional Interface)是Java 8引入的概念,指的是只包含一个抽象方法的接口。可以用@FunctionalInterface注解标记,也支持Lambda表达式方法引用

函数式接口类比

想象一个插座:

普通接口 = 复杂多功能插座(很多方法)
函数式接口 = 单一功能插座(只有一个功能)

函数式接口就像:
USB接口 → 只做一件事:充电/数据传输
而不是:
万能插座 → 什么都想做,什么都做不好

@FunctionalInterface注解

使用@FunctionalInterface注解可以让编译器帮助检查接口是否符合函数式接口的定义。

@FunctionalInterface
public interface MyFunction {
    int apply(int a, int b);
}

// 正确:只有一个抽象方法
@FunctionalInterface
interface Calculator {
    int calculate(int a, int b);
}

// 错误:多个抽象方法,编译报错
@FunctionalInterface
interface WrongInterface {
    void method1();
    void method2();  // 编译错误!
}

// 函数式接口也可以有默认方法(不计入抽象方法)
@FunctionalInterface
interface WithDefault {
    void execute();
    default void log() {  // 默认方法不计入抽象方法
        System.out.println("执行");
    }
}

四大核心函数式接口

接口抽象方法参数返回值用途
Predicate<T>test(T)1个boolean判断/过滤
Function<T,R>apply(T)1个R转换/映射
Consumer<T>accept(T)1个void消费/处理
Supplier<T>get()0个T生产/提供

Predicate - 判断接口

Predicate<T>接收一个参数,返回boolean值,用于判断条件

接口定义

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

    // 默认方法
    default Predicate and(Predicate other);
    default Predicate or(Predicate other);
    default Predicate negate();
    static  Predicate isEqual(Object targetRef);
}

基本使用

Predicate isEmpty = s -> s.isEmpty();
Predicate isNotEmpty = isEmpty.negate();

System.out.println(isEmpty.test(""));        // true
System.out.println(isNotEmpty.test("hello")); // true

Predicate isPositive = n -> n > 0;
System.out.println(isPositive.test(10));  // true
System.out.println(isPositive.test(-5)); // false

组合条件:and / or

Predicate isPositive = n -> n > 0;
Predicate isEven = n -> n % 2 == 0;

// and:同时满足
Predicate isPositiveEven = isPositive.and(isEven);
System.out.println(isPositiveEven.test(4));  // true (正数且偶数)
System.out.println(isPositiveEven.test(3));  // false (正数但奇数)

// or:满足其一
Predicate isPositiveOrEven = isPositive.or(isEven);
System.out.println(isPositiveOrEven.test(4));  // true (正数且偶数)
System.out.println(isPositiveOrEven.test(-2)); // true (负数但偶数)
System.out.println(isPositiveOrEven.test(-3)); // false (负数且奇数)

// negate:取反
Predicate isNotPositive = isPositive.negate();
System.out.println(isNotPositive.test(-5)); // true

isEqual静态方法

Predicate isJava = Predicate.isEqual("Java");
System.out.println(isJava.test("Java"));    // true
System.out.println(isJava.test("Python"));  // false

// 在Stream中使用
List languages = Arrays.asList("Java", "Python", "Java", "C++");
long javaCount = languages.stream()
    .filter(Predicate.isEqual("Java"))
    .count();
System.out.println("Java出现次数: " + javaCount);  // 2

Predicate在Stream中的应用

List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

// 过滤正数
List positives = numbers.stream()
    .filter(n -> n > 0)
    .collect(Collectors.toList());

// 过滤偶数
List evens = numbers.stream()
    .filter(n -> n % 2 == 0)
    .collect(Collectors.toList());

// 组合条件:大于5的奇数
List result = numbers.stream()
    .filter(n -> n > 5 && n % 2 != 0)
    .collect(Collectors.toList());

Function - 转换接口

Function<T,R>接收一个参数,返回一个结果,用于类型转换/映射

接口定义

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

    // 默认方法
    default  Function compose(Function before);
    default  Function andThen(Function after);
    static  Function identity();
}

基本使用

Function length = s -> s.length();
System.out.println(length.apply("hello"));  // 5

Function upper = s -> s.toUpperCase();
System.out.println(upper.apply("hello"));  // HELLO

Function toStr = i -> String.valueOf(i);
System.out.println(toStr.apply(100));  // "100"

链式调用:andThen / compose

Function trim = s -> s.trim();
Function upper = s -> s.toUpperCase();
Function toStr = s -> "Result: " + s;

// andThen:先执行当前,再执行after
Function pipeline1 = trim.andThen(upper).andThen(toStr);
System.out.println(pipeline1.apply("  hello  "));  // "Result: HELLO"

// compose:先执行before,再执行当前(顺序相反)
Function pipeline2 = toStr.compose(upper).compose(trim);
System.out.println(pipeline2.apply("  hello  "));  // "Result: HELLO"

// identity:返回输入本身
Function identity = Function.identity();
System.out.println(identity.apply("test"));  // "test"

多步转换示例

List names = Arrays.asList("  alice  ", "  BOB  ", "  Charlie  ");

// 链式转换:去空格 -> 转大写 -> 加前缀
List result = names.stream()
    .map(s -> s.trim())                    // 去空格
    .map(s -> s.toUpperCase())             // 转大写
    .map(s -> "Name: " + s)                // 加前缀
    .collect(Collectors.toList());

System.out.println(result);
// [Name: ALICE, Name: BOB, Name: CHARLIE]

Consumer - 消费接口

Consumer<T>接收一个参数,不返回结果,用于消费/处理数据

接口定义

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

    // 默认方法
    default Consumer andThen(Consumer after);
}

基本使用

Consumer printer = s -> System.out.println(s);
printer.accept("Hello World");  // 打印 Hello World

Consumer exclaimer = s -> System.out.println(s + "!");
printer.accept("Hi");    // 打印 Hi
exclaimer.accept("Hi");   // 打印 Hi!

andThen组合

Consumer trim = s -> System.out.println(s.trim());
Consumer upper = s -> System.out.println(s.toUpperCase());

// 先执行trim,再执行upper
Consumer consumer = trim.andThen(upper);
consumer.accept("  hello  ");
// 输出:
// hello
// HELLO

在Stream中使用

List names = Arrays.asList("Alice", "Bob", "Charlie");

// forEach接收Consumer
names.forEach(name -> System.out.println("Hello, " + name));
names.forEach(System.out::println);

// 打印每个元素的详细信息
names.forEach(name -> {
    System.out.println("==========");
    System.out.println("Name: " + name);
    System.out.println("Length: " + name.length());
});

Supplier - 生产接口

Supplier<T>不接收参数,返回一个结果,用于生产/提供数据

接口定义

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

基本使用

Supplier helloSupplier = () -> "Hello";
System.out.println(helloSupplier.get());  // "Hello"

// 创建对象
Supplier> listSupplier = () -> new ArrayList<>();
ArrayList list = listSupplier.get();
list.add("item");

// 创建Random对象
Supplier randomSupplier = Random::new;
Random random = randomSupplier.get();
System.out.println(random.nextInt(100));  // 0-99的随机数

实际应用场景

// 延迟计算/初始化
Supplier configSupplier = () -> loadConfiguration();
Configuration config = configSupplier.get();  // 实际使用时才加载

// 使用Optional
Optional optional = Optional.of("value");
// orElseGet是Supplier,当值为空时才调用
String value = optional.orElseGet(() -> "default");

// 方法引用创建对象
Supplier> listFactory = ArrayList::new;
Supplier> mapFactory = HashMap::new;

其他常用函数式接口

接口方法说明
BiPredicate<T,U>test(T,U)两个参数的判断
BiFunction<T,U,R>apply(T,U)两个参数的转换
BiConsumer<T,U>accept(T,U)两个参数的消费
UnaryOperator<T>apply(T)一元操作,结果同类型
BinaryOperator<T>apply(T,T)二元操作,结果同类型
IntPredicatetest(int)原始类型int的判断
IntFunction<R>apply(int)接收int,返回R
ToIntFunction<T>applyAsInt(T)返回int的转换

BiFunction示例

// 两个参数,返回一个结果
BiFunction concat = (s1, s2) -> s1 + s2;
System.out.println(concat.apply("Hello", "World"));  // "HelloWorld"

BiFunction add = (a, b) -> a + b;
System.out.println(add.apply(10, 20));  // 30

// 链式调用
BiFunction pipeline = concat.andThen(s -> s.toUpperCase());
System.out.println(pipeline.apply("hello", "world"));  // "HELLOWORLD"

UnaryOperator和BinaryOperator

// UnaryOperator:一元操作,输入输出类型相同
UnaryOperator square = n -> n * n;
System.out.println(square.apply(5));  // 25

UnaryOperator upper = String::toUpperCase;
System.out.println(upper.apply("hello"));  // HELLO

// BinaryOperator:二元操作,输入两个同类型值,返回同类型结果
BinaryOperator add = (a, b) -> a + b;
System.out.println(add.apply(10, 20));  // 30

BinaryOperator max = (s1, s2) -> s1.length() > s2.length() ? s1 : s2;
System.out.println(max.apply("apple", "banana"));  // "banana"

// 求最大值/最小值
BinaryOperator maxInt = BinaryOperator.maxBy(Integer::compare);
BinaryOperator minInt = BinaryOperator.minBy(Integer::compare);

原始类型函数式接口

// 避免自动装箱/拆箱,提高性能
IntFunction intToString = i -> String.valueOf(i);
System.out.println(intToString.apply(100));  // "100"

ToIntFunction strToLength = String::length;
System.out.println(strToLength.applyAsInt("hello"));  // 5

IntBinaryOperator sum = (a, b) -> a + b;
System.out.println(sum.applyAsInt(10, 20));  // 30

IntUnaryOperator doubleValue = n -> n * 2;
System.out.println(doubleValue.applyAsInt(5));  // 10

函数式接口的选择

需要判断? → Predicate
需要转换? → Function
需要处理但不返回? → Consumer
需要创建对象? → Supplier
两个参数? → Bi* 系列
避免装箱拆箱? → Int*/Long*/Double*

实战示例

构建查询条件

public class QueryBuilder {
    private List> conditions = new ArrayList<>();

    public QueryBuilder whenNameContains(String name) {
        conditions.add(s -> s.contains(name));
        return this;
    }

    public QueryBuilder whenNameStartsWith(String prefix) {
        conditions.add(s -> s.startsWith(prefix));
        return this;
    }

    public QueryBuilder whenNameNotEmpty() {
        conditions.add(s -> !s.isEmpty());
        return this;
    }

    public Predicate build() {
        Predicate result = s -> true;
        for (Predicate p : conditions) {
            result = result.and(p);
        }
        return result;
    }
}

// 使用
QueryBuilder builder = new QueryBuilder();
Predicate query = builder
    .whenNameNotEmpty()
    .whenNameStartsWith("A")
    .build();

System.out.println(query.test("Alice"));   // true
System.out.println(query.test("Bob"));     // false

数据转换流水线

public class DataPipeline {
    public static  List process(
            List data,
            Function mapper,
            Consumer consumer) {

        List result = data.stream()
            .map(mapper)
            .collect(Collectors.toList());

        result.forEach(consumer);
        return result;
    }
}

// 使用
List names = Arrays.asList("  alice  ", "  bob  ", "  charlie  ");

List processed = DataPipeline.process(
    names,
    s -> s.trim().toUpperCase(),           // Function
    s -> System.out.println("Processed: " + s)  // Consumer
);

System.out.println("Result: " + processed);

小结

  • 函数式接口是只有一个抽象方法的接口
  • @FunctionalInterface注解用于编译器检查
  • Predicate<T>:判断,返回boolean → filter()
  • Function<T,R>:转换,T→R → map()
  • Consumer<T>:消费,无返回值 → forEach()
  • Supplier<T>:生产,无参数 → orElseGet()
  • Bi* 系列:处理两个参数
  • 原始类型接口(Int*):避免装箱拆箱,提高性能
☕ Java 在线代码编辑器
📝 运行结果