Lab: pluggable browse rules¶
☕ Java 17 · The One-Method Contract Behind Every Lambda · 3/3
Goal: write one browse() method and give it any rule as a lambda, including a rule built by a default method.
Setup: in an empty folder, create ContentType.java, Content.java, ContentRule.java, StreamingPlatform.java and Main.java. No package.
Step 1 — The content¶
The record gives us title(), type() and rating().
Step 2 — The rule¶
@FunctionalInterface
public interface ContentRule {
boolean matches(Content c);
default ContentRule not() { return c -> !matches(c); }
}
matches() is the single abstract method. not() has a body, so it doesn't count: it returns a new rule that flips the answer.
Try adding boolean isPremium(Content c); under matches(): the compiler rejects @FunctionalInterface right away. Remove the line.
Step 3 — One browse method¶
import java.util.ArrayList;
import java.util.List;
public class StreamingPlatform {
private final List<Content> catalog = new ArrayList<>();
public void add(Content c) {
catalog.add(c);
}
public List<Content> browse(ContentRule rule) {
List<Content> result = new ArrayList<>();
for (Content c : catalog) {
if (rule.matches(c)) {
result.add(c);
}
}
return result;
}
}
browse() doesn't know what it filters for: the decision is plugged in from outside.
Step 4 — Three rules¶
import java.util.List;
public class Main {
public static void main(String[] args) {
StreamingPlatform platform = new StreamingPlatform();
platform.add(new Content("Inception", ContentType.MOVIE, 8.8));
platform.add(new Content("Stranger Things", ContentType.SERIES, 8.7));
platform.add(new Content("Red Notice", ContentType.MOVIE, 6.4));
platform.add(new Content("Our Planet", ContentType.DOCUMENTARY, 9.3));
platform.add(new Content("Emily in Paris", ContentType.SERIES, 6.9));
show("Movies only", platform.browse(c -> c.type() == ContentType.MOVIE));
show("Top rated (8.0+)", platform.browse(c -> c.rating() >= 8.0));
ContentRule moviesOnly = c -> c.type() == ContentType.MOVIE;
show("Hiding movies", platform.browse(moviesOnly.not()));
}
private static void show(String label, List<Content> list) {
System.out.println("=== " + label + " ===");
for (Content c : list) {
System.out.println(" " + c.title() + " (" + c.type() + ", " + c.rating() + ")");
}
System.out.println();
}
}
The third rule isn't written by hand: it asks the existing rule for its opposite.
Step 5 — Run¶
$ javac *.java
$ java Main
=== Movies only ===
Inception (MOVIE, 8.8)
Red Notice (MOVIE, 6.4)
=== Top rated (8.0+) ===
Inception (MOVIE, 8.8)
Stranger Things (SERIES, 8.7)
Our Planet (DOCUMENTARY, 9.3)
=== Hiding movies ===
Stranger Things (SERIES, 8.7)
Our Planet (DOCUMENTARY, 9.3)
Emily in Paris (SERIES, 6.9)
Three different results; browse() didn't change by a single character.
← @FunctionalInterface and Object methods · Back to the series
🎓 Preparing the OCP Java 17 exam? Exam traps and practice questions for this section → (optional)