User Tools

Site Tools


java:jfc_intf_sort

Differences

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

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
java:jfc_intf_sort [2020/03/10 15:35] – [Συγκρίνοντας με χρήσης ενός Comparator object] gthanosjava:jfc_intf_sort [Unknown date] (current) – external edit (Unknown date) 127.0.0.1
Line 1: Line 1:
-====== Ορίζοντας την σειρά καταχώρησης και ανάκτησης των δεδομένων ======+====== Ανίχνευση ισότητας και σύγκριση αντικειμένων ======
  
-Κατά κανόνα όταν θέλουμε να συγκρίνουμε επιμέρους αντικείμενα προκειμένου να ορίσουμε την σειρά αποθήκευσης και ανάκτησης τους σε μία δομή δεδομένων αυτό θα πρέπει να ακολουθεί κάποιους κανόνες. Για παράδειγμα, εάν συγκρίνουμε δύο 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?450 |}}+Εάν θέλουμε να αποθηκεύσουμε σε ένα //hash table// μία σειρά αντικειμένων θα πρέπει να είμαστε σίγουροι ότι δεν θα προστεθούν σε αυτό δύο ίδια αντικείμενα. Κατά συνέπεια, πρέπει να είμαστε σε θέση να προσδιορίσουμε με συνέπεια την ισότητα δύο αντικειμένων ιδίου τύπου.  
 + 
 +Προκειμένου να μπορούμε να ανιχνεύουμε την ισότητα μεταξύ αντικειμένων η Java παρέχει τις μεθόδους [[https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-|public boolean equals(Object obj)]] και [[https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#hashCode--|public int hashCode()]] της κλάσης [[https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html|java.lang.Object]]. Εάν θέλετε να μπορείτε να ανιχνεύσετε ισότητα/ανισότητα για τα αντικείμενα μίας κλάσης θα πρέπει να είναι υλοποιημένες __και οι δύο μέθοδοι__. Η μέθοδος //equals// επιστρέφει //true// εάν δύο αντικείμενα είναι ίσα, διαφορετικά επιστρέφει //false//. Η μέθοδος //hashCode// πρέπει να επιστρέφει την ίδια ακέραια τιμή για δύο διαφορετικά αλλά ίσα αντικείμενα.  
 + 
 +==== Υλοποιώντας την ισότητα αντικειμένων τύπου Student ====
  
-===== Υλοποιώντας το interface Comparable για δικούς μας τύπους δεδομένων =====+Παρακάτω δίνεται η κλάση Student ενημερωμένη ώστε να περιέχει τις υλοποιήσεις των συναρτήσεων [[https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-|equals]] και [[https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#hashCode--|hashCode]].
  
-Παρακάτω δίνεται η υλοποίηση του interface //Comparable// για την κλάση Student. 
 <code java Student.java> <code java Student.java>
-public class Student implements Comparable<Student> {+public class Student {
   private String firstName;   private String firstName;
   private String lastName;   private String lastName;
Line 16: Line 19:
     firstName = fname;     firstName = fname;
     lastName = lname;     lastName = lname;
 +  }
 +  
 +  public void setFirstName( String firstName ) {
 +    this.firstName = firstName;  
 +  }
 +  
 +  public void setLastName( String lastName ) {
 +    this.lastName = lastName;  
 +  }
 +  
 +  public String getFirstName() {
 +    return firstName;
 +  }
 +  
 +  public String getLastName() {
 +    return lastName;
   }   }
                
Line 23: Line 42:
      
   public boolean equals(Object o) {   public boolean equals(Object o) {
 +    if(o == null)
 +      return false;
     return (o instanceof Student && o.hashCode() == this.hashCode());     return (o instanceof Student && o.hashCode() == this.hashCode());
   }   }
Line 28: Line 49:
   public int hashCode() {   public int hashCode() {
     return 3 * firstName.hashCode() + 5 * lastName.hashCode();     return 3 * firstName.hashCode() + 5 * lastName.hashCode();
-  } 
-   
-  public int compareTo(Student st) { 
-    return lastName.compareTo(st.lastName) != 0 ? lastName.compareTo(st.lastName) : firstName.compareTo(st.firstName); 
   }   }
 } }
 </code> </code>
  
 +Παρατηρήστε ότι η μέθοδος equals επιστρέφει true εάν η παράμετρος ''Object ο'' είναι του τύπου της τρέχουσας κλάσης (δηλαδή Student) και έχει την ίδια τιμή hashCode με το τρέχον αντικείμενο. Αυτός είναι ένας τυπικός τρόπος για να ορίσετε τη συγκεκριμένη συνάρτηση.
  
-<code java StudentsSort.java+Η μέθοδος hashCode πρέπει να επιστρέφει την ίδια ακέραια τιμή για δύο ίσα αντικείμενα. Για το συγκεκριμένο παράδειγμα είναι αναγκαίο να έχουμε υπόψη μας ότι η κλάση [[https://docs.oracle.com/javase/8/docs/api/java/lang/String.html|java.lang.String]] υλοποιεί τη συνάρτηση [[https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#hashCode--|hashCode]] υπακούοντας στη συγκεκριμένη αρχήΗ υλοποίηση στη συνάρτηση Student αποκλείει να έχουμε δύο διαφορετικά αντικείμενα όπου το ένα είναι διαφορετικό από το άλλο αλλά έχουν το ίδιo hashCode().
-import java.util.*;+
  
-public class StudentsSort { +===== Σύγκριση αντικειμένων =====
-  public static void main(String[] args) { +
-    List<Student> list new ArrayList<>(); +
-    list.add(new Student("John", "Smith")); +
-    list.add(new Student("Karl", "Negt")); +
-    list.add(new Student("Jeff", "Smith")); +
-    list.add(new Student("Tom", "Rich"));+
  
-    Collections.sort(list); +Εάν θέλουμε να αποθηκεύσουμε αντικείμενα σε μία δεντρική δομή λεξικού (π.χ. [[https://docs.oracle.com/javase/8/docs/api/java/util/TreeSet.html|java.util.TreeSet]] είναι αναγκαίο να ορίσουμε τον τρόπο σύγκρισης των αντικειμένων μεταξύ τους. Η ίδια ανάγκη προκύπτει έαν θέλουμε να ταξινομήσουμε ένα σύνολο στοιχείων ή να εφαρμόσουμε δυαδική αναζήτηση σε ένα ήδη ταξινομημένο σύνολο. 
-    System.out.println(list);+ 
 +Η διαδικασία της σύγκρισης επιτυγχάνεται υλοποιώντας το //interface// [[http://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html|java.lang.Comparable]] (λεπτομέρειες [[java:comparable|εδώ]]), το οποίο ορίζει το κριτήριο σύγκρισης μεταξύ δύο αντικειμένων ιδίου τύπου. Οι κλάσεις της βασικής βιβλιοθήκης [[https://docs.oracle.com/javase/8/docs/api/java/lang/String.html|java.lang.String]], [[https://docs.oracle.com/javase/8/docs/api/java/util/Date.html|java.util.Date]] κ.α. υλοποιούν το συγκεκριμένο interface ορίζοντας τον κανόνα σύγκρισης μεταξύ δύο αντικειμένων. Παρακάτω δίνεται μία σειρά από δημοφιλείς κλάσεις της java και τα κριτήρια υλοποίησης του συγκεκριμένου interface για κάθε μία από αυτές. 
 + 
 +{{ :java:object-ordering.png?450 |}} 
 + 
 +==== Υλοποιώντας το interface Comparable για δικούς μας τύπους δεδομένων ==== 
 + 
 +Παρακάτω δίνεται η υλοποίηση του interface [[https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html|java.lang.Comparable]] για την κλάση Student. Η υλοποίηση της μεθόδου compareTo συγκρίνει τα επίθετα των δύο φοιτητών. Εάν είναι διαφορετικά επιστρέφει τη λεξικογραφική διαφορά τους. Εάν  είναι ίδια επιστρέφει τη λεξικογραφική διαφορά των ονομάτων τους. 
 + 
 +<code java Student.java> 
 +public class Student implements java.lang.Comparable<Student>
 +  private String firstName; 
 +  private String lastName; 
 +   
 +  public Student(String fname, String lname) { 
 +    firstName = fname; 
 +    lastName = lname; 
 +  } 
 +   
 +  public void setFirstName( String firstName ) { 
 +    this.firstName = firstName;   
 +  } 
 +   
 +  public void setLastName( String lastName ) { 
 +    this.lastName = lastName;   
 +  } 
 +   
 +  public String getFirstName() { 
 +    return firstName; 
 +  } 
 +   
 +  public String getLastName() { 
 +    return lastName; 
 +  } 
 +        
 +  public String toString() { 
 +    return firstName+" "+lastName; 
 +  } 
 +   
 +  public boolean equals(Object o) { 
 +    return (o instanceof Student && o.hashCode() == this.hashCode()); 
 +  } 
 +   
 +  public int hashCode() { 
 +    return 3 * firstName.hashCode() + 5 * lastName.hashCode(); 
 +  } 
 +   
 +  public int compareTo(Student st) { 
 +    return lastName.compareTo(st.lastName) != 0 ? lastName.compareTo(st.lastName) : firstName.compareTo(st.firstName);
   }   }
 } }
Line 56: Line 115:
 ===== Συγκρίνοντας με χρήση ενός Comparator object ===== ===== Συγκρίνοντας με χρήση ενός Comparator object =====
  
-Ας υποθέσουμε ότι θέλουμε να συγκρίνουμε αντικείμενα με διαφορετική μέθοδο από την μέθοδο με την οποία συγκρίνονται ή ότι θέλουμε να συγκρίνουμε αντικείμενα τα οποία δεν υλοποιούν το interface //Comparable//. Σε αυτή την περίπτωση θα χρειαστούμε ένα βοηθητικό αντικείμενο του τύπου [[http://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html|java.util.Comparator]], όπως παρακάτω+[[:java:comparable#%CF%84%CE%BF_interface_javautilcomparator|Επαναλαμβάνοντας τη συλλογιστική]] για το interface [[https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html|java.util.Comparator]], ας υποθέσουμε ότι θέλουμε να συγκρίνουμε τα αντικείμενα τύπου Student με διαφορετική πολιτική από αυτή που είναι υλοποιημένη στη μέθοδο ''compareTo'' ή ότι θέλουμε να συγκρίνουμε αντικείμενα τα οποία δεν υλοποιούν το interface //Comparable//. Σε αυτή την περίπτωση θα χρειαστούμε μία βοηθητική κλάση του τύπου [[http://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html|java.util.Comparator]]. Στο παρακάτω παράδειγμα, με τη βοήθεια της κλάσης StudentComparator γίνεται η σύγκριση αποκλειστικά με βάση το επίθετο και όχι με το συνδυασμό επίθετο και μικρό όνομα.
  
 <code java StudentComparator.java> <code java StudentComparator.java>
Line 67: Line 126:
 </code> </code>
  
-<code java> +|Προηγούμενο: [[:java:jfc_interfaces Interfaces ]] | [[:toc | Περιεχόμενα ]] | Επόμενο: [[:java:jfc_intf_collection java.util.Collection ]] |
-  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_map Interface java.util.Map ]] | [[:toc | Περιεχόμενα ]] | Επόμενο: [[:java:jfc_intf_sorted_set_map SortedSet και SortedMap ]] |+
  
java/jfc_intf_sort.1583854500.txt.gz · Last modified: 2020/03/10 15:35 by gthanos