Mastering Java Lambda: From Runnable to UnaryOperator Explained
This article explains how Java lambda expressions work by showing thread creation, collection sorting, and the underlying functional interfaces such as Runnable, Comparator, Function, and UnaryOperator, while clarifying the role of the @FunctionalInterface annotation and the compiler’s automatic detection of functional interfaces.
Java Lambda Usage and Source Code Analysis
Example: Running a Thread
new Thread(() -> System.out.print("hello world")).start();→ The lambda points to the Runnable interface.
Analysis
→ The arrow -> is the key operator of a lambda expression.
→ The expression is split into parameters (left) and body (right).
→ Thread constructor expects a Runnable object; the lambda is treated as an implementation of that functional interface.
→ The @FunctionalInterface annotation, introduced in JDK 8, marks an interface as a functional interface.
Case: Collection Sorting with a Comparator
List<String> list = new ArrayList<>();
Collections.sort(list, (o1, o2) -> {
if (o1.equals(o2)) {
return 1;
}
return -1;
});The second argument of Collections.sort is a Comparator<T> whose abstract method is int compare(T o1, T o2).
Question: Is @FunctionalInterface Required?
Even without the annotation, a lambda can be used as long as the target type satisfies the functional‑interface rules (exactly one abstract method, default methods do not count, methods from Object are ignored).
Source of @FunctionalInterface
package java.lang;
import java.lang.annotation.*;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface { }The Javadoc explains that the annotation is informative; the compiler enforces the same constraints whether the annotation is present or not.
UnaryOperator
@FunctionalInterface
public interface UnaryOperator<T> extends Function<T,T> {
static <T> UnaryOperator<T> identity() { return t -> t; }
}It inherits the single abstract method R apply(T t) from Function. The identity() method returns a function that returns its input unchanged.
Function Interface
@FunctionalInterface
public interface Function<T,R> {
R apply(T t);
default <V> Function<V,R> compose(Function<? super V,? extends T> before) { /* ... */ }
default <V> Function<T,V> andThen(Function<? super R,? extends V> after) { /* ... */ }
static <T> Function<T,T> identity() { return t -> t; }
}The abstract apply method is the method invoked by a lambda such as s -> s + "efg". Both UnaryOperator and Function are part of java.util.function, a utility package for reusable functional objects.
Key Takeaways
Lambda expressions are syntactic sugar for creating instances of functional interfaces.
The compiler automatically treats any interface that meets the functional‑interface criteria as a functional interface, even without the annotation.
Standard functional interfaces like Function, UnaryOperator, and Comparator simplify common patterns such as collection processing.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
