From a filter class to a lambda¶
โ Java 17 ยท Passing Behavior Around with Lambdas ยท 1/3
Thinking in functions¶
| Object style | Functional style |
|---|---|
| build objects, change their state | describe the result you want |
| write the loop step by step | pass small rules, let other code loop |
| focus on how | focus on what |
Java stays object-oriented: functional programming is an extra tool on top. Its key piece is the lambda: a block of code with parameters and a body, but no name, that you can pass to a method.
The scenario: filtering a catalog¶
public record Movie(String title, boolean isNew, boolean isKidFriendly) { }
public interface MovieFilter {
boolean test(Movie movie);
}
MovieFilter asks one question about a movie and answers with a boolean. A method can print every movie that passes any filter:
static void print(List<Movie> catalog, MovieFilter filter) {
for (Movie movie : catalog)
if (filter.test(movie))
System.out.print(movie.title() + " ");
System.out.println();
}
print() is nicely generic: it doesn't know which rule it applies.
The old way: one class per rule¶
public class KidFriendlyFilter implements MovieFilter {
public boolean test(Movie m) {
return m.isKidFriendly();
}
}
print(catalog, new KidFriendlyFilter());
A new file and a new class for a single expression. Every new rule means another class.
The new way: one line per rule¶
print(catalog, m -> m.isNew()); // new releases
print(catalog, m -> m.isKidFriendly()); // kid-friendly titles
print(catalog, m -> !m.isKidFriendly()); // everything not for kids
m -> m.isNew() reads as given a movie m, keep it if it's new. print() didn't change: it still expects a MovieFilter, and Java turns the lambda into one.
Code now, run later¶
- You write the lambda.
print(catalog, m -> m.isNew());checks no movie yet: it hands code toprint(). - Java matches it to the interface.
print()expects aMovieFilter, whose only abstract method isboolean test(Movie movie). Somis aMovieand the body must produce aboolean. print()runs it later, once per movie, when it callsfilter.test(movie).
A lambda always needs a context that tells Java what it is: here, the MovieFilter parameter. That context is called the target type.
Lambdas can be written in several forms, from long to very short. The next page goes through every rule.