19 Java BiFunction 和 BinaryOperator

本文为个人学习摘要笔记。 原文地址: Java8 函数式接口 BiFunction 使用教程 Java8 函数式接口 BinaryOperator 使用教程

Java 常用函数接口:

BiFunction

BiFunction 可以接受两个参数并返回一个结果。

@FunctionalInterface
public interface BiFunction<T, U, R> {
    R apply(T t, U u);
}
  • T – 第一个参数的类型;

  • U – 第二个参数的类型;

  • R – 返回结果的类型。

基本用法

// 两数相加
BiFunction<Integer, Integer, Integer> addFunc = Integer::sum;
System.out.println(addFunc.apply(1, 2)); // 3

// 两数取幂
BiFunction<Integer, Integer, Double> powFunc = Math::pow;
System.out.println(powFunc.apply(2, 3)); // 8.0

// 两数之和转 List
BiFunction<Integer, Integer, List<Integer>> listFunc = (x1, x2) -> Collections.singletonList(x1 + x2);
System.out.println(listFunc.apply(4, 6)); // [10]

串联 Function<T, R>

// 两数相加
BiFunction<Integer, Integer, Integer> addFunc = Integer::sum;

// Integer to String
Function<Integer, String> int2strFunc = String::valueOf;

System.out.println(addFunc.andThen(int2strFunc).apply(1, 2)); // 3

封装:

public static void main(String[] args) {
    String result = convert(1, 2, Integer::sum, String::valueOf);
    System.out.println(result); // 3
}

private static <A1, A2, R1, R2> R2 convert(A1 a1, A2 a2, BiFunction<A1, A2, R1> func, Function<R1, R2> func2) {
    return func.andThen(func2).apply(a1, a2);
}

工厂模式

public class Java8BiFunction1 {

    public static void main(String[] args) {
        GPS gps = factory("40.741895", "-73.989308", GPS::new);
        System.out.println(gps);
    }

    public static <R extends GPS> R factory(String Latitude, String Longitude,
                                            BiFunction<String, String, R> func) {
        return func.apply(Latitude, Longitude);
    }
}

class GPS {
    private String Latitude;
    private String Longitude;

    GPS(String latitude, String longitude) {
        Latitude = latitude;
        Longitude = longitude;
    }

    @Override
    public String toString() {
        return "GPS{" +
                "Latitude='" + Latitude + '\'' +
                ", Longitude='" + Longitude + '\'' +
                '}';
    }
}

BinaryOperator

在 Java8 中 BinaryOperator 继承自 BiFunction,同样也是一个函数式接口。BinaryOperator 可以接受两个类型为 T 的参数,返回一个类型为 T 的结果。

@FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T, T, T> {}

替换 BiFunction

当 BiFunction 的两个参数类型与返回值类型都是同一类型的时候,我们可以使用 BinaryOperator 替换 BiFunction,比如可以用 BinaryOperator<Integer> 替换 BiFunction<Integer, Integer, Integer>

// BiFunction 和 BinaryOperator 两者等价
BiFunction<Integer, Integer, Integer> func = Integer::sum;
BinaryOperator<Integer> func2 = Integer::sum;

计算最大/最小值

BinaryOperator 提供两个方法比较大小:

  • maxBy() 方法可以返回两个参数中较大的值,它的实现相当于三目表达式:a > b ? a : b

  • minBy() 方法可以返回两个参数中较小的值,它的实现相当于三目表达式:a < b ? a : b

如果将 maxBy()minBy() 用于对象的比较还需要实现一个自定义的 Comparator 接口。

public class Java8BiFunction1 {

    public static void main(String[] args) {
        Developer dev1 = new Developer("jordan", BigDecimal.valueOf(9999));
        Developer dev2 = new Developer("jack", BigDecimal.valueOf(8888));
        Developer dev3 = new Developer("jaden", BigDecimal.valueOf(10000));
        Developer dev4 = new Developer("ali", BigDecimal.valueOf(2000));
        Developer dev5 = new Developer("myexample", BigDecimal.valueOf(1));
        List<Developer> list = Arrays.asList(dev1, dev2, dev3, dev4, dev5);

        // 1. 创建一个Comparator,使用码农的工资作为排序
        Comparator<Developer> comparing = Comparator.comparing(Developer::getSalary);
        // 2. 使用maxBy方法创建一个BinaryOperator用于返回两参数中较大的值
        BinaryOperator<Developer> bo = BinaryOperator.maxBy(comparing);

        Developer result = find(list, bo);
        System.out.println(result);     // Developer{name='jaden', salary=10000}

        // 合并在一起
        // 寻找工资最高的程序员
        Developer developer = find(list, BinaryOperator.maxBy(Comparator.comparing(Developer::getSalary)));
        System.out.println(developer);  // Developer{name='jaden', salary=10000}
        // 寻找工资最低的程序员
        Developer developer2 = find(list, BinaryOperator.minBy(Comparator.comparing(Developer::getSalary)));
        System.out.println(developer2); // Developer{name='myexample', salary=1}
    }

    private static Developer find(List<Developer> list, BinaryOperator<Developer> accumulator) {
        Developer result = null;
        for (Developer t : list) {
            if (result == null) {
                result = t;
            } else {
                result = accumulator.apply(result, t);
            }
        }
        return result;
    }
}

class Developer {
    private String name;
    private BigDecimal salary;

    public Developer(String name, BigDecimal salary) {
        this.name = name;
        this.salary = salary;
    }

    public BigDecimal getSalary() {
        return salary;
    }
}

最后更新于