ZetCode

Java UnaryOperator 接口

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

java.util.function.UnaryOperator 接口表示对单个操作数执行操作,并产生相同类型的结果。它扩展了 Function 接口,并且是一个函数式接口,具有 apply 方法。UnaryOperator 常用在输入和输出类型匹配的转换中。

UnaryOperator 是 Java 8 中新增的 Java 函数式编程实用程序的一部分。它专门用于输入和输出类型相同的情况,简化了类型声明并提供了类型安全。

UnaryOperator 接口概述

UnaryOperator 接口包含一个从 Function 继承的抽象方法和几个静态方法。关键方法 apply 对输入执行操作。静态方法提供有用的运算符实例。

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

以上代码展示了 UnaryOperator 接口的结构。它通过相同的输入和输出类型扩展了 Function。identity 方法返回一个 UnaryOperator,该运算符始终返回其输入参数。

UnaryOperator 的基本用法

使用 UnaryOperator 最简单的方法是使用 lambda 表达式。我们定义如何将输入转换为相同类型的输出。示例对整数进行平方。

Main.java
package com.zetcode;

import java.util.function.UnaryOperator;

public class Main {

    public static void main(String[] args) {

        // Define a UnaryOperator that squares integers
        UnaryOperator<Integer> square = x -> x * x;
        
        // Apply the operator
        System.out.println("Square of 5: " + square.apply(5));
        System.out.println("Square of 12: " + square.apply(12));
        
        // UnaryOperator using method reference
        UnaryOperator<String> toUpper = String::toUpperCase;
        System.out.println("Uppercase: " + toUpper.apply("hello"));
    }
}

此示例演示了使用 lambda 和方法引用的 UnaryOperator 基本用法。square 运算符接受 Integer 并返回 Integer。toUpper 运算符将字符串转换为大写。两者都保持输入-输出类型。

UnaryOperator 组合

UnaryOperator 从 Function 继承组合方法。andThencompose 允许链接操作,同时保持类型一致性。这创建了强大的转换管道。

Main.java
package com.zetcode;

import java.util.function.UnaryOperator;

public class Main {

    public static void main(String[] args) {

        // First operator increments by 1
        UnaryOperator<Integer> increment = x -> x + 1;
        
        // Second operator multiplies by 2
        UnaryOperator<Integer> doubler = x -> x * 2;
        
        // Compose the operators
        UnaryOperator<Integer> incrementThenDouble = increment.andThen(doubler);
        UnaryOperator<Integer> doubleThenIncrement = doubler.andThen(increment);
        
        System.out.println("Increment then double 5: " + incrementThenDouble.apply(5));
        System.out.println("Double then increment 5: " + doubleThenIncrement.apply(5));
    }
}

此示例展示了 UnaryOperator 组合。我们在保持 Integer 类型的同时链接数学运算。运算顺序会显着影响最终结果。

UnaryOperator Identity(恒等式)

UnaryOperator.identity 方法返回一个运算符,该运算符始终不加修改地返回其输入参数。它在转换管道中用作默认或中性操作。

Main.java
package com.zetcode;

import java.util.function.UnaryOperator;

public class Main {

    public static void main(String[] args) {

        // Identity operator
        UnaryOperator<String> identity = UnaryOperator.identity();
        
        System.out.println("Identity applied: " + identity.apply("test"));
        
        // Practical use with optional transformation
        UnaryOperator<String> transformer = someCondition() 
            ? String::toUpperCase 
            : UnaryOperator.identity();
            
        System.out.println("Result: " + transformer.apply("conditional"));
    }
    
    private static boolean someCondition() {
        return false;
    }
}

此示例演示了 UnaryOperator.identity。identity 运算符不加修改地返回其输入。当需要条件转换但有时不需要操作时,它用作中性元素。

将 UnaryOperator 与 Streams 一起使用

UnaryOperator 与 Java Streams 自然地协同工作,用于原地转换。当输入和输出类型匹配时,map 操作接受 UnaryOperator。这可以实现干净的数据处理管道。

Main.java
package com.zetcode;

import java.util.Arrays;
import java.util.List;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;

public class Main {

    public static void main(String[] args) {

        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        
        // UnaryOperator to square numbers
        UnaryOperator<Integer> square = x -> x * x;
        
        // Apply operator in stream
        List<Integer> squaredNumbers = numbers.stream()
            .map(square)
            .collect(Collectors.toList());
            
        System.out.println("Original: " + numbers);
        System.out.println("Squared: " + squaredNumbers);
    }
}

此示例展示了在 Streams 中使用 UnaryOperator。我们定义了一个平方运算符,并通过 map 将其应用于每个流元素。结果是一个新列表,其中包含转换后的值,同时始终保持 Integer 类型。

UnaryOperator 用于字符串操作

UnaryOperator 尤其适用于字符串转换,其中操作保留 String 类型。常见示例包括修剪、大小写转换和格式化。

Main.java
package com.zetcode;

import java.util.function.UnaryOperator;

public class Main {

    public static void main(String[] args) {

        // Trim and capitalize string
        UnaryOperator<String> trimAndCapitalize = s -> {
            String trimmed = s.trim();
            return trimmed.substring(0, 1).toUpperCase() + 
                   trimmed.substring(1).toLowerCase();
        };
        
        System.out.println("Formatted: " + trimAndCapitalize.apply("  hELLO  "));
        
        // Repeat string three times
        UnaryOperator<String> tripler = s -> s + s + s;
        System.out.println("Tripled: " + tripler.apply("hi"));
    }
}

此示例演示了使用 UnaryOperator 进行字符串操作。我们创建了用于清理和格式化字符串的运算符,同时保持 String 类型。这些运算符可以在不同的字符串处理场景中重复使用。

专门化的 UnaryOperator 变体

Java 为原始类型提供了专门化的 UnaryOperator 变体,以避免装箱开销。这些包括 IntUnaryOperatorLongUnaryOperatorDoubleUnaryOperator

Main.java
package com.zetcode;

import java.util.function.IntUnaryOperator;
import java.util.function.DoubleUnaryOperator;

public class Main {

    public static void main(String[] args) {

        // IntUnaryOperator example
        IntUnaryOperator negate = x -> -x;
        System.out.println("Negated: " + negate.applyAsInt(42));
        
        // DoubleUnaryOperator example
        DoubleUnaryOperator celsiusToFahrenheit = c -> (c * 9/5) + 32;
        System.out.println("20°C in Fahrenheit: " + 
            celsiusToFahrenheit.applyAsDouble(20));
    }
}

此示例展示了专门化的 UnaryOperator 变体。IntUnaryOperator 直接与 int 原语一起使用,避免了 Integer 装箱。同样,DoubleUnaryOperator 可以有效地处理 double 原语。

来源

Java UnaryOperator 接口文档

在本文中,我们介绍了 Java UnaryOperator 接口的基本方法和特性。理解这些概念对于函数式编程和流处理中的类型安全转换至关重要。

作者

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

列出所有Java教程