All 15 Functional Interfaces & Method References questions
More in Functional Interfaces & Method References
Advertisement
Back to results for “Generics”
Java › Functional Interfaces & Method References

What is the difference between UnaryOperator<T> and Function<T,T>, and why does UnaryOperator exist as a separate, more specific interface?

Intermediate

Answer

UnaryOperator<T> extends Function<T,T> (a function whose input and output are the same type), existing as a more specific, semantically clearer name specifically for the common case where a transformation preserves its input's type (like a String-to-String transformation, or doubling a number) -- functionally it's interchangeable with Function<T,T> (inheriting the same apply() method plus andThen/compose), but using UnaryOperator communicates the same-type constraint more clearly to readers and provides a convenient static identity() factory method that Function alone doesn't offer with quite the same clarity.
UnaryOperator<String> toUpper = String::toUpperCase;
UnaryOperator<Integer> square = x -> x * x;

// Equivalent to Function<String, String> and Function<Integer, Integer>, but more semantically clear
UnaryOperator<String> identity = UnaryOperator.identity();  // returns its input unchanged
System.out.println(identity.apply("test"));  // "test"
Real-world example A List.replaceAll() call (which specifically requires a UnaryOperator<T> parameter, not just any Function<T,T>) is used to transform every element of a list in place, the API deliberately choosing the more semantically specific UnaryOperator type to communicate that the transformation must preserve the list's element type.

Common follow-ups: What's the equivalent 'BinaryOperator' interface, and what use case does it serve for combining two same-typed values?;Why does List.replaceAll() specifically require UnaryOperator rather than accepting a general Function?