Before Java 8, if you wanted to pass a piece of logic to a method, you typically had to create an anonymous inner class. This resulted in “vertical” code—lots of boilerplate just to say one thing. Lambda Expressions solved this by providing a clear and concise way to represent functions.
What is a Lambda Expression?
A lambda expression is an anonymous function (a function without a name). It doesn’t belong to any class and can be passed around as if it were an object.
The basic syntax is: (parameters) -> { body }
The Transformation: From Anonymous Class to Lambda
Imagine you want to sort a list of strings by their length.
The Old Way (Anonymous Inner Class):
Comparator<String> lengthComparator = new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return Integer.compare(s1.length(), s2.length());
}
};
The New Way (Lambda Expression):
Comparator<String> lengthComparator = (s1, s2) -> Integer.compare(s1.length(), s2.length());
The compiler is smart enough to know that s1 and s2 are Strings because they are being assigned to a Comparator<String>.
Functional Interfaces
Lambdas can only be used where a Functional Interface is expected. A functional interface is an interface with exactly one abstract method.
Common examples include:
Runnable(method:void run())Comparator(method:int compare(T o1, T o2))Predicate(method:boolean test(T t))Consumer(method:void accept(T t))
You can mark your own interfaces with @FunctionalInterface to ensure they follow this rule.
@FunctionalInterface
public interface Greeting {
void sayHello(String name);
}
// Usage
Greeting g = name -> System.out.println("Hello, " + name);
g.sayHello("Aman");
Method References: The Ultimate Shortcut
If a lambda just calls an existing method, you can often use a Method Reference (::) to make it even cleaner.
// Lambda
list.forEach(item -> System.out.println(item));
// Method Reference
list.forEach(System.out::println);
Real-World Example: Event Handling
In a GUI or a web framework, you often need to handle events. Lambdas make this incredibly clean.
// Without Lambda
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
saveData();
}
});
// With Lambda
button.addActionListener(e -> saveData());
Conclusion
Lambda expressions were the key that unlocked functional programming in Java. They make your code more readable by focusing on the “what” instead of the “how.” By embracing lambdas and functional interfaces, you can write Java code that is more expressive, less error-prone, and much more enjoyable to maintain.