Lambdas (Java 8+) είναι συνοπτικές ανώνυμες συναρτήσεις, και μια λειτουργική διεπαφή είναι μια διεπαφή με ακριβώς μια αφηρημένη μέθοδο — ο τύπος στόχος που υλοποιεί ένα lambda. Μαζί ανέφεραν συναρτησιακό προγραμματισμό στη Java και δίνουν ισχύ στο Stream API.
Ένα λειτουργικό interface
@FunctionalInterface // optional annotation — enforces ONE abstract method
interface Calculator {
int calculate(int a, int b); // the single abstract method
}
Μια διεπαφή με μια αφηρημένη μέθοδο είναι "λειτουργική" — ένα lambda μπορεί να την υλοποιήσει γιατί δεν υπάρχει ασάφεια σχετικά με το ποια μέθοδο αντιπροσωπεύει το lambda.
Σύνταξη Lambda — υλοποιήστε την συνοπτικά
// ❌ verbose anonymous class (pre-Java 8)
Calculator add = new Calculator() {
public int calculate(int a, int b) { return a + b; }
};
// ✅ lambda — same thing, far less boilerplate
Calculator add = (a, b) -> a + b;
Calculator multiply = (a, b) -> a * b;
add.calculate(2, 3); // 5
Το lambda (a, b) -> a + b παρέχει την υλοποίηση της μοναδικής μεθόδου — χωρίς κλάση, χωρίς υπόδειγμα υπογραφής μεθόδου.
Ενσωματωμένες λειτουργικές διεπαφές (java.util.function)
Function<String, Integer> length = s -> s.length(); // takes T, returns R
Predicate<Integer> isPositive = n -> n > 0; // takes T, returns boolean
Consumer<String> printer = s -> System.out.println(s); // takes T, returns void
Supplier<String> greeting = () -> "Hello"; // takes nothing, returns T
BiFunction<Integer, Integer, Integer> sum = (a, b) -> a + b; // two args
Η Java παρέχει έτοιμες λειτουργικές διεπαφές για κοινά σχήματα, που χρησιμοποιούνται σε ολόκληρη τη βιβλιοθήκη κατάστασης (ειδικά streams).
Αναφορές μεθόδου — ακόμη συντομότερη
// when a lambda just calls an existing method, use a method reference
list.forEach(System.out::println); // instead of x -> System.out.println(x)
list.stream().map(String::toUpperCase); // instead of s -> s.toUpperCase()
list.stream().map(Integer::parseInt); // static method ref
Όπου τα lambdas λάμπουν
// passing behavior as arguments — the core enabler of the Stream API
people.stream()
.filter(p -> p.getAge() > 18) // Predicate lambda
.map(Person::getName) // method reference
.forEach(System.out::println); // Consumer
list.sort((a, b) -> a.compareTo(b)); // Comparator lambda
button.addActionListener(e -> handleClick()); // event handler
Γιατί έχει σημασία
Τα lambdas και οι λειτουργικές διεπαφές ανέφεραν τον συναρτησιακό προγραμματισμό στη Java, αλλάζοντας θεμελιωδώς τον τρόπο γραφής της σύγχρονης Java.
Εξαλείφουν το περίπλοκο υπόδειγμα ανώνυμης κλάσης για τη διέλευση συμπεριφοράς ως δεδομένων, ενεργοποιώντας συνοπτικά χειριστήρια συμβάντων, συγκριτές, επανακλήσεις και — κυρίως — ολόκληρο το Stream API (το οποίο εξαρτάται από lambdas για τις λειτουργίες filter/map/reduce).
Η κατανόηση ότι ένα lambda στοχεύει σε μια λειτουργική διεπαφή (μια αφηρημένη μέθοδο), τις ενσωματωμένες διεπαφές (Function, Predicate, Consumer, Supplier) και τις αναφορές μεθόδου είναι απαραίτητη για τη σύνταξη ιδιωματικής σύγχρονης Java και τη αποτελεσματική χρήση streams, συλλογών και ταυτόχρονων API.
Αντιπροσωπεύουν μια σημαντική εξέλιξη της γλώσσας και είναι ουσιαστικές για την τρέχουσα ευχέρεια Java.
