常用函数式接口的解读及使用

tech2026-01-24  4

常用函数式接口的解读及使用

前言版本Supplierdemo Consumerdemo Predicatedemo Functiondemo UnaryOperatordemo BinaryOperatordemo 总结

前言

Java8 以来推出的 lambda 表达式使得程序员的代码越来越 优雅,配合 函数式接口 一起使用,很多繁杂的代码可以变得十分的 轻巧 。官方也在 java.util.function 下为我们提供了很多 函数式接口,本章节做个简单地梳理

版本

JDK11

Supplier

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

不需要参数,但返回一个结果,不吃光吐,生产者

针对不同类型的结果,还提供了 IntSupplier DoubleSupplier 等类

demo

public class SupplierTest { @Test public void test1() { s(() -> "hello"); // s(String::new); is(() -> 1); } private void s(Supplier supplier) { System.out.println(supplier.get()); } private void is(IntSupplier intSupplier) { System.out.println(intSupplier.getAsInt() * 2); } }

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); }; } }

接受一个参数,但没有返回值,只吃不吐,消费者

提供了 andThen 方法,允许后缀一个 Consumer 再消费一次

BiConsumer 接受两个参数

同样地,也提供了其他类型参数的 Consumer 比如 DoubleConsumer ObjDoubleConsumer 等

demo

public class ConsumerTest { @Test public void test1() { c(1, System.out::println); bc(1, 2, (i, j) -> System.out.print( Integer.parseInt(i.toString()) + Integer.parseInt(j.toString()) + " = ")); } private void c(int i, Consumer consumer) { consumer.andThen(j -> System.out.println(" = " + j)).accept(i); } private void bc(int i, int j, BiConsumer biConsumer) { biConsumer.andThen((x, y) -> System.out.println(x +" + "+ y)).accept(i, j); } } 结果: 1 = 1 3 = 1 + 2

Predicate

@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); } @SuppressWarnings("unchecked") static <T> Predicate<T> not(Predicate<? super T> target) { Objects.requireNonNull(target); return (Predicate<T>)target.negate(); } }

接受一个参数,返回一个 boolean 值

提供了三个默认方法 and negate or,方法名 和 方法的实现语义 都特别清晰,及对应了 &&(与) !(非) ||(或) 逻辑运算

还提供了两个静态方法 isEqual 返回一个语义为 是否与 targetRef 相等的 Predicate not 其实相当于 target.negate()

BiPredicate 接受两个参数,且不提供上述两个静态方法

同样地,也提供了针对其他类型参数的 IntPredicate DoublePredicate 等等

demo

public class PredicateTest { @Test public void test1() { p(1, i -> Integer.parseInt(i.toString()) > 0, i -> Integer.parseInt(i.toString()) < 0); System.out.println("==========================================="); System.out.println(Predicate.not(Predicate.isEqual("0")).test("1")); // true } private void p(int i, Predicate p1, Predicate p2) { System.out.println(p1.test(i)); // true System.out.println(p2.test(i)); // false System.out.println(p1.and(p2).test(i)); // false System.out.println(p1.or(p2).test(i)); // true System.out.println(p1.negate().test(i)); // false } }

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; } }

接受一个参数,返回一个参数

提供了 compose 方法在当前 Function 之前执行,返回值用于当前 Function 。andThen 方法在当前 Function 之后执行,以当前 Function 的返回值为参数

提供了一个静态方法 identity ,返回一个啥也不干的 Function

BiFunction 接受两个参数,返回一个参数,只提供了默认方法 andThen

同样的,针对其他类型参数提供了 DoubleFunction DoubleToIntFunction 等

demo

public class FunctionTest { @Test public void test1() { f(1 , i -> Integer.parseInt(i.toString()) - 1 , i -> Integer.parseInt(i.toString()) * 2); } public void f(int i, Function f1, Function f2) { System.out.println(f1.compose(f2).apply(i)); System.out.println(f1.andThen(f2).apply(i)); } } 结果: 1 0

UnaryOperator

@FunctionalInterface public interface UnaryOperator<T> extends Function<T, T> { static <T> UnaryOperator<T> identity() { return t -> t; } }

Function 的子类,即入参和结果类型一致的 Function ,提供了静态方法 identity 获取 UnaryOperator 实例

同样的,针对不同类型的参数还有 DoubleUnaryOperator IntUnaryOperator 等

demo

public class UnaryOperatorTest { @Test public void test1() { u(1, UnaryOperator.identity()); } public void u(int i, UnaryOperator unaryOperator) { System.out.println(unaryOperator.apply(i)); // 1 } }

BinaryOperator

@FunctionalInterface public interface BinaryOperator<T> extends BiFunction<T,T,T> { public static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) { Objects.requireNonNull(comparator); return (a, b) -> comparator.compare(a, b) <= 0 ? a : b; } public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) { Objects.requireNonNull(comparator); return (a, b) -> comparator.compare(a, b) >= 0 ? a : b; } }

BiFunction 的子类,即两个入参和返回值的类型都一致的 BiFunction

提供了两个静态方法,minBy 根据传入的 Comparator 方法入参里的较小值, maxBy 相反

针对不同类型的参数,提供了 IntBinaryOperator DoubleBinaryOperator 等类

demo

public class BinaryOperatorTest { @Test public void bo() { System.out.println(BinaryOperator .maxBy((a, b) -> ((User) a).id - ((User) b).id) .apply(new User(1), new User(2))); System.out.println(BinaryOperator .minBy((a, b) -> ((User) a).id - ((User) b).id) .apply(new User(1), new User(2))); } class User { int id; public User(int id) { this.id = id; } @Override public String toString() { return "User{" + "id='" + id + '\'' + '}'; } } } 结果: User{id='2'} User{id='1'}

总结

以上 函数式接口 基本涵盖了日常开发能用到的所有场景,使用起来及其舒适

最新回复(0)