ZetCode

Java BinaryOperator 接口

最后修改时间:2025 年 4 月 16 日

java.util.function.BinaryOperator 接口表示对两个相同类型的操作数执行的操作,并产生相同类型的结果。 它扩展了 BiFunction,并且是一个具有单个抽象方法 apply 的函数式接口。

BinaryOperator 是 Java 8 中添加的 Java 函数式编程实用程序的一部分。 它通常用于归约操作、数学计算和组合值。 该接口提供了静态方法用于常见的操作,例如 min 和 max。

BinaryOperator 接口概述

BinaryOperator 接口包含一个抽象方法和几个静态方法。 关键方法 apply 对两个输入执行操作。 静态方法提供常见的二元操作。

@FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T,T,T> {
    static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator);
    static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator);
}

上面的代码显示了 BinaryOperator 接口的结构。 它使用泛型,其中 T 是操作数和结果的类型。 该接口扩展了 BiFunction,并且所有三个类型参数都相同。

基本的 BinaryOperator 用法

使用 BinaryOperator 最简单的方法是使用 lambda 表达式。 我们定义如何组合两个相同类型的值。 该示例显示了整数的加法。

Main.java
package com.zetcode;

import java.util.function.BinaryOperator;

public class Main {

    public static void main(String[] args) {

        // Define a binary operator for addition
        BinaryOperator<Integer> adder = (a, b) -> a + b;
        
        // Apply the operator
        System.out.println("Sum of 5 and 3: " + adder.apply(5, 3));
        System.out.println("Sum of 10 and 15: " + adder.apply(10, 15));
        
        // BinaryOperator for string concatenation
        BinaryOperator<String> concat = (s1, s2) -> s1 + s2;
        System.out.println("Concatenated: " + concat.apply("Hello ", "World"));
    }
}

此示例演示了带有 lambda 表达式的基本 BinaryOperator 用法。 adder 接受两个整数并返回它们的总和。 concat 运算符组合两个字符串。 BinaryOperator 适用于任何组合两个相同类型值的操作。

使用 minBy 和 maxBy

minBymaxBy 静态方法创建 BinaryOperator,根据 Comparator 返回两个值的最小值或最大值。 这对于归约操作很有用。

Main.java
package com.zetcode;

import java.util.Comparator;
import java.util.function.BinaryOperator;

public class Main {

    public static void main(String[] args) {

        // Create min and max operators for integers
        BinaryOperator<Integer> minOp = BinaryOperator.minBy(Integer::compare);
        BinaryOperator<Integer> maxOp = BinaryOperator.maxBy(Integer::compare);
        
        System.out.println("Min of 5 and 3: " + minOp.apply(5, 3));
        System.out.println("Max of 5 and 3: " + maxOp.apply(5, 3));
        
        // For custom objects
        BinaryOperator<String> shortest = 
            BinaryOperator.minBy(Comparator.comparingInt(String::length));
        System.out.println("Shorter string: " + 
            shortest.apply("longword", "short"));
    }
}

此示例显示了如何使用 minBymaxBy。 我们创建查找最小值和最大值的运算符。 对于自定义对象,我们提供一个 Comparator。 这些方法通常与流一起使用。

Stream 归约中的 BinaryOperator

BinaryOperator 通常用作流归约操作中的累加器。 reduce 方法采用 BinaryOperator 来组合流元素。 这对于聚合操作非常强大。

Main.java
package com.zetcode;

import java.util.Arrays;
import java.util.List;
import java.util.function.BinaryOperator;

public class Main {

    public static void main(String[] args) {

        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        
        // BinaryOperator for sum
        BinaryOperator<Integer> sum = (a, b) -> a + b;
        
        // Reduce the stream
        int total = numbers.stream()
            .reduce(0, sum);
            
        System.out.println("Sum of numbers: " + total);
        
        // Product of numbers
        BinaryOperator<Integer> product = (a, b) -> a * b;
        int factorial = numbers.stream()
            .reduce(1, product);
            
        System.out.println("Product of numbers: " + factorial);
    }
}

此示例演示了 stream 归约中的 BinaryOperator。 我们定义了用于求和和求积的运算符。 reduce 方法使用这些运算符来聚合流元素。 这种模式在数据处理中很常见。

与其他函数式接口组合

BinaryOperator 可以与其他函数式接口(如 Function 和 Predicate)组合,以创建更复杂的操作。 这使得可以构建强大的数据处理管道。

Main.java
package com.zetcode;

import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Predicate;

public class Main {

    public static void main(String[] args) {

        // BinaryOperator for sum
        BinaryOperator<Integer> sum = (a, b) -> a + b;
        
        // Function to square a number
        Function<Integer, Integer> square = x -> x * x;
        
        // Predicate to check if even
        Predicate<Integer> isEven = x -> x % 2 == 0;
        
        // Combined operation
        int result = sum.andThen(square).apply(3, 4);
        System.out.println("Sum squared: " + result);
        
        // Conditional operation
        BinaryOperator<Integer> conditionalOp = (a, b) -> 
            isEven.test(a) ? sum.apply(a, b) : a * b;
        System.out.println("Conditional result: " + conditionalOp.apply(4, 5));
        System.out.println("Conditional result: " + conditionalOp.apply(3, 5));
    }
}

此示例显示了将 BinaryOperator 与其他函数式接口结合使用。 我们使用 andThen 链接操作,并使用 Predicate 创建条件逻辑。 这展示了 Java 中函数式编程的灵活性。

具有自定义对象的 BinaryOperator

BinaryOperator 与自定义对象以及与原始类型一样有效。 我们可以定义将两个对象组合成一个对象的操作。 这对于特定于域的操作很有用。

Main.java
package com.zetcode;

import java.util.function.BinaryOperator;

class Point {
    int x;
    int y;
    
    Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
    
    @Override
    public String toString() {
        return "(" + x + "," + y + ")";
    }
}

public class Main {

    public static void main(String[] args) {

        // BinaryOperator to add two points
        BinaryOperator<Point> pointAdder = (p1, p2) -> 
            new Point(p1.x + p2.x, p1.y + p2.y);
            
        Point p1 = new Point(1, 2);
        Point p2 = new Point(3, 4);
        
        System.out.println("Sum of points: " + pointAdder.apply(p1, p2));
        
        // BinaryOperator to find midpoint
        BinaryOperator<Point> midpoint = (p1, p2) -> 
            new Point((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
            
        System.out.println("Midpoint: " + midpoint.apply(p1, p2));
    }
}

此示例演示了具有自定义 Point 对象的 BinaryOperator。 我们定义了用于添加点和查找中点的操作。 相同的模式可以应用于任何需要组合操作的域对象。

并行流中的 BinaryOperator

并行流中使用的 BinaryOperator 必须是结合律,以确保正确的结果。 无论分组如何,该操作都必须产生相同的结果。 这对于并行处理至关重要。

Main.java
package com.zetcode;

import java.util.Arrays;
import java.util.List;
import java.util.function.BinaryOperator;

public class Main {

    public static void main(String[] args) {

        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        
        // Associative BinaryOperator for sum
        BinaryOperator<Integer> sum = (a, b) -> a + b;
        
        // Parallel stream reduction
        int parallelSum = numbers.parallelStream()
            .reduce(0, sum);
            
        System.out.println("Parallel sum: " + parallelSum);
        
        // Non-associative operation (subtraction)
        BinaryOperator<Integer> subtract = (a, b) -> a - b;
        int parallelSubtract = numbers.parallelStream()
            .reduce(0, subtract);
            
        System.out.println("Parallel subtract (incorrect): " + parallelSubtract);
    }
}

此示例显示了并行流中结合律的重要性。 sum 操作在并行中正常工作,因为它是结合律的。 减法失败,因为它不是结合律的。 始终验证并行操作的结合律。

用于数学运算的 BinaryOperator

BinaryOperator 非常适合实现采用两个操作数的数学运算。 我们可以创建可重用的运算符用于各种计算,并灵活地组合它们。

Main.java
package com.zetcode;

import java.util.function.BinaryOperator;

public class Main {

    public static void main(String[] args) {

        // Mathematical operators
        BinaryOperator<Double> add = (a, b) -> a + b;
        BinaryOperator<Double> multiply = (a, b) -> a * b;
        BinaryOperator<Double> power = (a, b) -> Math.pow(a, b);
        
        // Using the operators
        System.out.println("5 + 3 = " + add.apply(5.0, 3.0));
        System.out.println("5 * 3 = " + multiply.apply(5.0, 3.0));
        System.out.println("5 ^ 3 = " + power.apply(5.0, 3.0));
        
        // Combining operations
        double result = add.andThen(x -> multiply.apply(x, 2.0))
                          .apply(3.0, 4.0);
        System.out.println("(3 + 4) * 2 = " + result);
    }
}

此示例显示了用于数学运算的 BinaryOperator。 我们定义了基本的算术运算符并演示了它们的使用。 这些运算符可以组合起来形成更复杂的计算,展示了函数式组合的强大功能。

来源

Java BinaryOperator 接口文档

在本文中,我们介绍了 Java BinaryOperator 接口的基本方法和功能。 理解这些概念对于现代 Java 应用程序中的归约操作和函数式编程至关重要。

作者

我叫 Jan Bodnar,是一位在该领域拥有多年经验的专注程序员。 我于 2007 年开始撰写编程文章,此后撰写了 1,400 多篇文章和八本电子书。 凭借超过八年的教学经验,我致力于分享我的知识并帮助他人掌握编程概念。

列出所有Java教程