java:jfc_intf_sort

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
java:jfc_intf_sort [2015/03/17 12:30]
gthanos created
java:jfc_intf_sort [2017/05/12 12:18] (current)
gthanos [Υλοποιώντας το interface Comparable για δικούς μας τύπους δεδομένων]
Line 1: Line 1:
 ====== Ορίζοντας την σειρά καταχώρησης και ανάκτησης των δεδομένων ====== ====== Ορίζοντας την σειρά καταχώρησης και ανάκτησης των δεδομένων ======
  
-Κατά κανόνα όταν θέλουμε να συγκρίνουμε επιμέρους αντικείμενα προκειμένου να ορίσουμε την σειρά αποθήκευσης και ανάκτησης τους σε μία δομή δεδομένων αυτό θα πρέπει να ακολουθεί κάποιους κανόνες. Για παράδειγμα,​ εάν συγκρίνουμε δύο String, αυτά θα συγκριθούν με βάση συγκεκριμένα κριτήρια λεξικού. Αντίστοιχα,​ αν συγκρίνουμε δύο ημερομηνίες αυτές θα συγκριθούν με βάση τις ημερομηνίες που αντιπροσωπεύουν. Γενικότερα στην java ορίζεται το interface //​[[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​lang/​Comparable.html|Comparable]]//​ το οποίο ορίζει τα κριτήρια σύγκρισης δύο ​ίδιων ​αντικειμένων ​μεταξύ ​τους. Οι κλάσεις String, Date, Integer κ.α. υλοποιούν το συγκεκριμένο interface ορίζοντας τους κανόνες σύγκρισης. Παρακάτω δίνεται μία σειρά από δημοφιλείς κλάσεις της java και τα κριτήρια υλοποίησης του συγκεκριμένου interface για κάθε μία από αυτές.+Κατά κανόνα όταν θέλουμε να συγκρίνουμε επιμέρους αντικείμενα προκειμένου να ορίσουμε την σειρά αποθήκευσης και ανάκτησης τους σε μία δομή δεδομένων αυτό θα πρέπει να ακολουθεί κάποιους κανόνες. Για παράδειγμα,​ εάν συγκρίνουμε δύο String, αυτά θα συγκριθούν με βάση συγκεκριμένα κριτήρια λεξικού. Αντίστοιχα,​ αν συγκρίνουμε δύο ημερομηνίες αυτές θα συγκριθούν με βάση τις ημερομηνίες που αντιπροσωπεύουν. Γενικότερα στην java ορίζεται το interface //​[[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​lang/​Comparable.html|Comparable]]//​ το οποίο ορίζει τα κριτήρια σύγκρισης ​μεταξύ ​δύο αντικειμένων του ιδίου ​τύπου. Οι κλάσεις της standard βιβλιοθήκης String, Date, Integer κ.α. υλοποιούν το συγκεκριμένο interface ορίζοντας τους κανόνες σύγκρισης. Παρακάτω δίνεται μία σειρά από δημοφιλείς κλάσεις της java και τα κριτήρια υλοποίησης του συγκεκριμένου interface για κάθε μία από αυτές.
  
-{{ :​java:​object-ordering.png |}}+{{ :​java:​object-ordering.png?450 |}}
  
 ===== Υλοποιώντας το interface Comparable για δικούς μας τύπους δεδομένων ===== ===== Υλοποιώντας το interface Comparable για δικούς μας τύπους δεδομένων =====
Line 48: Line 48:
 Τα βασικά χαρακτηριστικά της παραπάνω κλάσης είναι τα εξής: Τα βασικά χαρακτηριστικά της παραπάνω κλάσης είναι τα εξής:
   * Έλεγχος στον κατασκευαστή εάν περνάνε ή όχι null ορίσματα. Αυτό μας προστατεύει από το να έρθουμε αντιμέτωποι με //​NullPointerException//​ στην συνέχεια.   * Έλεγχος στον κατασκευαστή εάν περνάνε ή όχι null ορίσματα. Αυτό μας προστατεύει από το να έρθουμε αντιμέτωποι με //​NullPointerException//​ στην συνέχεια.
-  * Η μέθοδος //hashCode()// επαναπροσδιορίζεται. +  * Η μέθοδος //equals()// επαναπροσδιορίζεται, έτσι ώστε να συγκρίνονται τα πεδία της κλάσης Name μεταξύ τους
-  * Η μέθοδος //equal()// επαναπροσδιορίζεται.+  * Η μέθοδος //hashCode()// επαναπροσδιορίζεται. Ο λόγος που πρέπει να επαναπροσδιορίσουμε την μέθοδο αυτή είναι ότι εξ' ορισμού δύο ίδια αντικείμενα θα πρέπει να έχουν και ίδια //​hashCodes//​. Εφόσον άλλαξε η μέθοδος //equal()// θα αλλάξει και η μέθοδος //​hashCode()//​ ώστε να επιστρέφει το ίδιο hash για αντικείμενα που η equals επιστρέφει ισότητα.
   * Υλοποιείται η μέθοδος //int comparTo(T t)//.   * Υλοποιείται η μέθοδος //int comparTo(T t)//.
  
 +<WRAP 85% center round tip>
 +Εξ' ορισμού (εάν δεν την επαναπροσδιορίσετε) η μέθοδος [[https://​docs.oracle.com/​javase/​8/​docs/​api/​java/​lang/​Object.html#​equals-java.lang.Object-|equals]],​ [[http://​docs.oracle.com/​javase/​tutorial/​java/​IandI/​objectclass.html|συγκρίνει δύο αντικείμενα με βάση την διεύθυνση του κάθε αντικειμένου]]. Στην πραγματικότητα επιστρέφει ισότητα __μόνο αν τα references των δύο αντικειμένων είναι ίδια__, δηλ. και οι δύο μεταβλητές δείχνουν στο ίδιο αντικείμενο. Στην πλειοψηφία των περιπτώσεων ο συγκεκριμένος τρόπος σύκρισης δεν μας δίνει στην πράξη ικανοποιητικό αποτελέσμα,​ καθώς αγνοεί αντικείμενα με τα ίδια περιεχόμενα.
 +
 +Σε αναλογία η μέθοδος [[https://​docs.oracle.com/​javase/​8/​docs/​api/​java/​lang/​Object.html#​hashCode--|hashCode]] επιστρέφει την δεκαεξαδική τιμή που δείχνει η μεταβλητή του αντικειμένου στην μνήμη. Με δεδομένο ότι __για δύο ίδια αντικείμενα τα hashCodes τους θα πρέπει να είναι κοινά__,​ η default υλοποίηση ταιριάζει με την default υλοποίηση της μεθόδου //equals//. Αν όμως αλλάξει η υλοποίηση της //equals// σε μία κλάση θα πρέπει να αλλάξει και η //​hashCode()//​ ώστε δύο ίδια αντικείμενα κατά την μέθοδο //equals// να έχουν και ίδια hashCodes.
 +</​WRAP>​
 +
 +<code java NameSort.java>​
 +import java.util.*;​
 +
 +public class NameSort {
 +    public static void main(String[] args) {
 +        Name nameArray[] = {
 +            new Name("​John",​ "​Smith"​),​
 +            new Name("​Karl",​ "​Ng"​),​
 +            new Name("​Jeff",​ "​Smith"​),​
 +            new Name("​Tom",​ "​Rich"​)
 +        };
 +
 +        List<​Name>​ names = Arrays.asList(nameArray);​
 +        Collections.sort(names);​
 +        System.out.println(names);​
 +    }
 +}
 +</​code>​
 +
 +===== Συγκρίνοντας με χρήσης ενός Comparator object =====
 +
 +Ας υποθέσουμε ότι θέλουμε να συγκρίνουμε αντικείμενα με διαφορετική μέθοδο από την μέθοδο με την οποία συγκρίνονται ή ότι θέλουμε να συγκρίνουμε αντικείμενα τα οποία δεν υλοποιούν το interface //​Comparable//​. Σε αυτή την περίπτωση θα χρειαστείουμε ένα βοηθητικό αντικείμενο του τύπου [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​util/​Comparator.html|Comparator]],​ όπως παρακάτω
 +
 +<code java NameComparatorSort.java>​
 +import java.util.*;​
 +public class NameComparatorSort {
 +    static final Comparator<​Name>​ NameOrdering = 
 +                                        new Comparator<​Name>​() {
 +            public int compare(Name n1, Name n2) {
 +                int cmp = n1.firstName().compareTo(n2.firstName() );
 +                return (cmp != 0 ? cmp : n1.lastName().compareTo(n2.lastName() ));
 +            }
 +    };
 +
 +    public static void main(String[] args) {
 +        Name nameArray[] = {
 +            new Name("​John",​ "​Smith"​),​
 +            new Name("​Karl",​ "​Ng"​),​
 +            new Name("​Jeff",​ "​Smith"​),​
 +            new Name("​Tom",​ "​Rich"​)
 +        };
 +        Collections.sort(Arrays.asList(nameArray),​ NameOrdering);​
 +        for(Name n: nameArray)
 +        System.out.println(n);​
 +    }
 +}
 +</​code>​
 +
 +Ο συγκεκριμένος //​Comparator//​ μας δίνει την δυνατότητα να αλλάξουμε την μέθοδο με την οποία συγκρίνονται τα αντικείμενα του συγκεκριμένου τύπου δεδομένων δίνοντας προτεραιότητα στο μικρό όνομα αντί για το επίθετο.
  
java/jfc_intf_sort.1426595419.txt.gz · Last modified: 2016/02/26 11:15 (external edit)