An easy way to understand UnaryOperator functional Interface in Java8.
What is it ?
UnaryOperator is a functional interface introduced in Java 8 in the java.util.function package.
It represents a function that takes one argument and returns a result of the same type.
It’s particularly useful when the input and output types are the same.
It extends the Function interface, which is a functional interface representing a function that accepts one argument and produces a result.
UnaryOperator has only one abstract method, apply(T t), which is inherited from the Function interface.
The apply(T t) method takes an object of type T as input and returns an object of the same type T.
Additional Insights:
It’s part of the java.util.function package, introduced in Java 8 to support functional programming concepts.
It’s often used for transformations on individual values or filtering elements within streams.
It can be combined with other unary operators or functions using and Then or compose methods for more complex operations.
Why we should use it?
UnaryOperator in this case promotes code clarity, type safety, reusability, functional composition, and potential performance benefits through parallelism.
It aligns well with functional programming principles and effectively handles string transformations in a concise and expressive manner.
@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {
// No additional abstract methods;
//inherits apply(T t) from Function<T, T>
}
@FunctionalInterface
public interface Function<T, R> {
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
R apply(T t);
Before using Lambdas and streams, let’s look at the traditional way .
package steams.examples;
import java.util.function.UnaryOperator;
public class UnaryOperatorExample implements UnaryOperator<String> {
@Override
public String apply(String name) {
return "Hello, " + name;
}
public static void main(String[] args) {
UnaryOperator<String> uo = new UnaryOperatorExample();
String result = uo.apply("Dean Winchester");
System.out.println(result); // output- Hello, Dean Winchester
}
}
Now lets look at the Java8 way.
With int
public class UnaryOperatorInt {
public static void main(String[] args) {
// Define a UnaryOperator to increment an integer by 1
// using a lambda expression for conciseness
UnaryOperator<Integer> incrementByOne = x -> x + 1;
// Store the original value
int originalValue = 5;
// Apply the UnaryOperator to the original value
// to get the incremented result
int result = incrementByOne.apply(originalValue);
// Print the original value and the incremented result
System.out.println("Original value: " + originalValue);
System.out.println("Result after incrementing by one: " + result);
}
}
output
Original value: 5
Result after incrementing by one: 6
int with Streams
package steams.examples;
import java.util.Arrays;
import java.util.List;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
public class UnaryOperatorIntWithStream {
public static void main(String[] args) {
// Define a UnaryOperator that increments an integer by one
UnaryOperator<Integer> incrementByOne = x -> x + 1;
// Create a list of original integer values
List<Integer> originalValues = Arrays.asList(1, 2, 3, 4, 5);
// Apply the UnaryOperator to each integer value using a stream
List<Integer> results = originalValues.stream()
.map(incrementByOne) // Apply the UnaryOperator to each element
.collect(Collectors.toList()); // Collect the results into a new list
// Print the original list of integer values
System.out.println("Original values: " + originalValues);
// Print the list of results after applying the UnaryOperator
System.out.println("Results after incrementing by one: " + results);
}
}
With String
package steams.examples;
import java.util.Arrays;
import java.util.List;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
public class UnaryOperatorLambda {
public static void main(String[] args) {
// Define a UnaryOperator to convert a string to uppercase and trim whitespace
UnaryOperator<String> stringProcessor = s -> s.toUpperCase().trim();
// s.toUpperCase().trim() from java.lang.String class
// Apply the UnaryOperator to a single input text
String inputText = " example text ";
String processedText = stringProcessor.apply(inputText);
// Print the original and processed text
System.out.println("Original text: " + inputText);
System.out.println("Processed text: " + processedText);
// Now let;s look at it with a Steam
// Reassign the UnaryOperator to the same operation
stringProcessor = s -> s.toUpperCase().trim();
// Create a list of input texts
List<String> inputTexts = Arrays.asList(" example text ", " another example ", " one more example ");
// Apply the UnaryOperator to each input text in the list using a stream
List<String> processedTexts = inputTexts.stream()
.map(stringProcessor)
.collect(Collectors.toList());
// Print the original and processed texts from the list
System.out.println("Original texts from the list: " + inputTexts);
System.out.println("Processed texts from the list: " + processedTexts);
}
}
Output
Original text: example text
Processed text: EXAMPLE TEXT
Original texts from the list: [ example text , another example , one more example ]
Processed texts from the list: [EXAMPLE TEXT, ANOTHER EXAMPLE, ONE MORE EXAMPLE]