Java's UnaryOperator in Lambda expressions example

The implementation of Java 8 Lambda expressions required an introduction to a number of new interfaces with esoteric names that can be somewhat intimidating to developers without any experience in functional programming. One such area is the functional UnaryOperator interface.

It may be academically named, but is incredibly simple in terms of its purpose and implementation.

The function of the UnaryOpertor

The function of the UnaryOperator interface is to take an object, do something with it and then return an object of the same type. That’s the unary nature of the function. One object type goes in, and the exact same type goes out.

For a more technical discussion, you can see from the UnaryOperator JavaDoc that the component extends the Function interface and defines a single method named apply.

java.util.function.UnaryOperator
@FunctionalInterface
public interface UnaryOperator<T> extends Function<T,T>

T apply(T t)
Applies this function to the given argument.

Parameter Types:
T - the input given to the function
T - the result running the function

For example, perhaps you wanted to strip out all of the non-numeric characters from a String. In that case, a String that contains a bunch of digits and letters would go into the UnaryOperator, and a String with nothing but numbers would be returned. A String goes in and a String comes out. That’s a UnaryOperator in action.

Definition of the term unary.

Definition of the term unary.

 

Implementation of the UnaryOperator example

To show you an old school, pre-Java 8 UnaryOperator example, we will create a single class named UnaryOperatorExample and provide the required apply method. The apply method is the single method required by all classes that implement the UnaryOperator interface.

We will use generics in the class declaration, <String>, to indicate this UnaryOpeartor’s apply method works exclusively on String objects, but this UnaryOperator interface is certainly not limited to just the text based data. You can genericize the interface with any valid Java class.

package com.mcnz.lambda;

import java.util.function.UnaryOperator;
// Create class that implements the UnaryOperator interface
public class UnaryOperatorExample implements UnaryOperator<String>{
  public String apply(String text) {
    return text+".txt";
  }
}

class UnaryOperatorTest {
  public static void main(String args[]){
     UnaryOperatorExample uoe = new UnaryOperatorExample();

     String text = "lambda-tutorial";
     String newText = uoe.apply(text);
     System.out.println(newText);
  }
}

When the class is executed, the result is the text string lambda-tutorial.txt written to the console.

Example UnaryOperator Lambda expression

If you implement the UnaryOperator interface with a complete Java class, it will create completely valid code, but it defeats the purpose of working with a functional interface. The whole idea of functional programming is to write code that uses very sparse and concise lambda expressions. With a lambda expression, we can completely eliminate the need for the UnaryOperatorExample class and rewrite the entire application as such:

package com.mcnz.lambda;
import java.util.function.UnaryOperator;
// A UnaryOperator Lambda expression example
class UnaryOperatorTest {
  public static void main(String args[]){
    UnaryOperator<String> extensionAdder = (String text) -> { return text + ".txt";} ;
    String newText = extensionAdder.apply("example-function");
    System.out.println(newText);
  }
}

One of the goals of the lambda expression framework is to simplify the Java language and eliminate as much ceremony from the code as possible. As such, it should come as no surprise to discover that we can simplify our lambda expression further by re-writing the highlighted line of code:

UnaryOperator<String> extensionAdder = (text) -> text + ".txt" ;

Java API use of the UnaryOperator function

With functions now tightly embedded throughout the Java API, interfaces such as the aforementioned Consumer interface, and the current UnaryOperator tend to pop up everywhere. One of its most notable usages is an argument to the iterate method of the Stream class.

static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)

For the uninitiated, a method signature like this can be intimidating, but as this UnaryOperator example has demonstrated, the implementation of a lambda expression that simply takes and returns an object of the same data type really couldn’t be easier. And that’s the whole idea behind the lambda project — that in the end, Java programs will be both easier to read and easier to write.

App Architecture
Software Quality
Cloud Computing
Security
SearchAWS
Close