User Tools

Site Tools


java:jfc_intf_sort

Ανίχνευση ισότητας και σύγκριση αντικειμένων

Ανίχνευση ισότητας αντικειμένων

Εάν θέλουμε να αποθηκεύσουμε σε ένα hash table μία σειρά αντικειμένων θα πρέπει να είμαστε σίγουροι ότι δεν θα προστεθούν σε αυτό δύο ίδια αντικείμενα. Κατά συνέπεια, πρέπει να είμαστε σε θέση να προσδιορίσουμε με συνέπεια την ισότητα δύο αντικειμένων ιδίου τύπου.

Προκειμένου να μπορούμε να ανιχνεύουμε την ισότητα μεταξύ αντικειμένων η Java παρέχει τις μεθόδους public boolean equals(Object obj) και public int hashCode() της κλάσης java.lang.Object. Εάν θέλετε να μπορείτε να ανιχνεύσετε ισότητα/ανισότητα για τα αντικείμενα μίας κλάσης θα πρέπει να είναι υλοποιημένες και οι δύο μέθοδοι. Η μέθοδος equals επιστρέφει true εάν δύο αντικείμενα είναι ίσα, διαφορετικά επιστρέφει false. Η μέθοδος hashCode πρέπει να επιστρέφει την ίδια ακέραια τιμή για δύο διαφορετικά αλλά ίσα αντικείμενα.

Υλοποιώντας την ισότητα αντικειμένων τύπου Student

Παρακάτω δίνεται η κλάση Student ενημερωμένη ώστε να περιέχει τις υλοποιήσεις των συναρτήσεων equals και hashCode.

Student.java
public class 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) {
    if(o == null)
      return false;
    return (o instanceof Student && o.hashCode() == this.hashCode());
  }
 
  public int hashCode() {
    return 3 * firstName.hashCode() + 5 * lastName.hashCode();
  }
}

Παρατηρήστε ότι η μέθοδος equals επιστρέφει true εάν η παράμετρος Object ο είναι του τύπου της τρέχουσας κλάσης (δηλαδή Student) και έχει την ίδια τιμή hashCode με το τρέχον αντικείμενο. Αυτός είναι ένας τυπικός τρόπος για να ορίσετε τη συγκεκριμένη συνάρτηση.

Η μέθοδος hashCode πρέπει να επιστρέφει την ίδια ακέραια τιμή για δύο ίσα αντικείμενα. Για το συγκεκριμένο παράδειγμα είναι αναγκαίο να έχουμε υπόψη μας ότι η κλάση java.lang.String υλοποιεί τη συνάρτηση hashCode υπακούοντας στη συγκεκριμένη αρχή. Η υλοποίηση στη συνάρτηση Student αποκλείει να έχουμε δύο διαφορετικά αντικείμενα όπου το ένα είναι διαφορετικό από το άλλο αλλά έχουν το ίδιo hashCode().

Σύγκριση αντικειμένων

Εάν θέλουμε να αποθηκεύσουμε αντικείμενα σε μία δεντρική δομή λεξικού (π.χ. java.util.TreeSet είναι αναγκαίο να ορίσουμε τον τρόπο σύγκρισης των αντικειμένων μεταξύ τους. Η ίδια ανάγκη προκύπτει έαν θέλουμε να ταξινομήσουμε ένα σύνολο στοιχείων ή να εφαρμόσουμε δυαδική αναζήτηση σε ένα ήδη ταξινομημένο σύνολο.

Η διαδικασία της σύγκρισης επιτυγχάνεται υλοποιώντας το interface java.lang.Comparable (λεπτομέρειες εδώ), το οποίο ορίζει το κριτήριο σύγκρισης μεταξύ δύο αντικειμένων ιδίου τύπου. Οι κλάσεις της βασικής βιβλιοθήκης java.lang.String, java.util.Date κ.α. υλοποιούν το συγκεκριμένο interface ορίζοντας τον κανόνα σύγκρισης μεταξύ δύο αντικειμένων. Παρακάτω δίνεται μία σειρά από δημοφιλείς κλάσεις της java και τα κριτήρια υλοποίησης του συγκεκριμένου interface για κάθε μία από αυτές.

Υλοποιώντας το interface Comparable για δικούς μας τύπους δεδομένων

Παρακάτω δίνεται η υλοποίηση του interface java.lang.Comparable για την κλάση Student. Η υλοποίηση της μεθόδου compareTo συγκρίνει τα επίθετα των δύο φοιτητών. Εάν είναι διαφορετικά επιστρέφει τη λεξικογραφική διαφορά τους. Εάν είναι ίδια επιστρέφει τη λεξικογραφική διαφορά των ονομάτων τους.

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);
  }
}

Συγκρίνοντας με χρήση ενός Comparator object

Επαναλαμβάνοντας τη συλλογιστική για το interface java.util.Comparator, ας υποθέσουμε ότι θέλουμε να συγκρίνουμε τα αντικείμενα τύπου Student με διαφορετική πολιτική από αυτή που είναι υλοποιημένη στη μέθοδο compareTo ή ότι θέλουμε να συγκρίνουμε αντικείμενα τα οποία δεν υλοποιούν το interface Comparable. Σε αυτή την περίπτωση θα χρειαστούμε μία βοηθητική κλάση του τύπου java.util.Comparator. Στο παρακάτω παράδειγμα, με τη βοήθεια της κλάσης StudentComparator γίνεται η σύγκριση αποκλειστικά με βάση το επίθετο και όχι με το συνδυασμό επίθετο και μικρό όνομα.

StudentComparator.java
import java.util.*;
public class StudentComparator implements java.util.Comparator<Student> {
  public int compare(Student s1, Student s2) {
    return s1.getLastName().compareTo(s2.getLastName());
  }
}
java/jfc_intf_sort.txt · Last modified: 2021/04/05 06:13 (external edit)