This is an old revision of the document!
Table of Contents
Functional Interfaces
Τα Functional Interfaces είναι ένα από τα νεότερα χαρακτηριστικά που προστέθηκαν στη Java από την έκδοση 8 και μετά. Αποτελούν απαραίτητα στοιχεία για την γραφή προγραμμάτων με μία μη-αντικειμενοστραφή (συναρτησιακή λογική) την οποία θα δούμε στη συνέχεια.
Τι είναι ένα Functional Interface;
Ένα Functional Interface είναι ένα interface το οποίο περιέχει ακριβώς μία abstract (αφηρημένη) μέθοδο. Μπορεί να έχει επιπλέον default ή static μεθόδους τις οποίες όμως δεν υπολογίζμε διότι έχουν ήδη κάποια υλοποίηση.
Συνήθως, φέρει την προαιρετική σήμανση (annotation) @FunctionalInterface πριν από τη δήλωση του Functional Interface. Αυτή η σήμανση ενημερώνει τον compiler να βγάλει σφάλμα αν κατά λάθος προσθέσουμε και δεύτερη αφηρημένη μέθοδο.
Γνωστό παράδειγμα, functional interface είναι το java.util.Comparator που λειτουργεί ως συγκριτής και επιτρέπει τη σύγκριση δύο αντικειμένων μεταξύ τους.
Χρήση του Functional Interface java.util.Comparator
Ας υποθέσουμε ότι έχουμε την κλάση Student (κατεβάστε τον κώδικα) που περιέχει δύο private πεδία τα όνομα και το επίθετο του φοιτητή. Ας υποθέσουμε ότι έχουμε μία λίστα φοιτητών και θέλουμε να τους ταξινομήσουμε με τη βοήθεια της μεθόδου sort της κλάσης java.util.Collections.
Ταξιονομούμε τους φοιτητές με βάση το επίθετο τους, με τη βοήθεια του παρακάτω συγκριτή:
- StudentComparator.java
public class StudentComparator<Student> implements java.util.Compator<Student> { int compare(Student a, Student b) { return a.getLastName().compareTo(b.getLastName()); } }
- SortStudents.java
import java.util.Comparator; import java.util.Arrays; import java.util.Collections; import java.util.List; public class StudentSorter { public static void main(String[] args) { List<Student> list = Arrays.asList( new Student("Minnie", "Mouse"), new Student("Mickey", "Gouse"), new Student("Marry", "Poppins"), new Student("Peter", "Pan") ); System.out.println(list); Collections.sort(list, new StudentComparator()) ); System.out.println(list); } }
Παρατηρήστε ότι για να ταξινομήσουμε τα αντικείμενα πρέπει να φτιάξουμε ένα αντικείμενο της κλάσης StudentComparator. Θα μπορούσαμε να αποφύγουμε τη σύνταξη του κώδικα της κλάσης StudentComparator και του αντικειμένου αυτής με χρήση ενός lamda expression ως εξής:
- SortStudents.java
import java.util.Comparator; import java.util.Arrays; import java.util.Collections; import java.util.List; public class StudentSorter { public static void main(String[] args) { List<Student> list = Arrays.asList( new Student("Minnie", "Mouse"), new Student("Mickey", "Gouse"), new Student("Marry", "Poppins"), new Student("Peter", "Pan") ); System.out.println(list); Collections.sort(list, (a,b) -> a.getLastName().compareTo(b.getLastName()) ); System.out.println(list); } }
H έκφραση (a,b) → a.getLastName().compareTo(b.getLastName()) αποτελεί ένα lamda expression και μπορείτε να το δείτε ως μία ανώνυμη συνάρτηση, που αποτελεί την υλοποίηση της μοναδικής abstract μεθόδου του αντίστοιχου Functional Interface. Περισσότερα για τα lamda expressions θα δούμε στη συνέχεια.
Ορισμός ενός δικού μας Functional Interface
Ας υποθέσουμε ότι έχουμε το interface CustomHasher<T>, το οποίο παρέχει την υλοποίση ενός hash function για κάθε διαφορετικό τύπο δεδομένων T, όπως αυτό περιγράφεται παρακάτω:
- CustomHasher.java
@FunctionalInterface public interface CustomHasher<T> { public long hash(T t); }
Ας υποθέσουμε τώρα ότι για την κλάση του φοιτητή υλοποιούμε τον παρακάτω CustomHasher
- StudentHasher.java
public class StudentHasher implements CustomHasher<Student> { public long hash(Student s) { unsigned long value = 5381; for (char c : s.getLastName().toCharArray()) { value = ((value << 5) + value) + (int)c; } value << 1; for (char c : s.getFirstName().toCharArray()) { value = ((value << 5) + value) + (int)c; } return value; } }
O κώδικας για να γίνει hash ένας φοιτητής δίνεται παρακάτω
- HashStudent.java
public class StudentHasher { public static void main(String[] args) { Student st = new Student("giorgos", "Thanos"); StudentHasher sh = new StudentHasher(); System.out.println("Hash is: "+sh.hash(st)); } }
Οι δύο παραπάνω κλάσεις με τη βοήθεια lamda expression θα μπορούσαν να γραφούν ως εξής:
- HashStudent.java
{ public class HashStudent { public static void main(String[] args) { Student giorgos = new Student("giorgos", "Thanos"); CustomHasher<Student> hs = (s) -> { long value = 5381; for (char c : s.getLastName().toCharArray()) { value = ((value << 3) + value) + (int)c; } for (char c : s.getFirstName().toCharArray()) { value = ((value << 3) + value) + (int)c; } return value; }; System.out.println("Hash is: "+ hs.hash(giorgos) ); } } }
