Sitelet https://coddy.tech/learn/he/java/object_oriented_programming/equals_and_hashcode
Menu
CoddyTech

equals() ו-hashCode()

חלק מהיחידה תכנות מונחה עצמים במסלול ה-Java של Coddy. שיעור 42 מתוך 87.

בעת השוואת אובייקטים ב-Java, האופרטור == בודק אם שתי הפניות מצביעות לאותו מיקום בזיכרון. כדי להשוות את התוכן בפועל של אובייקטים, צריך לדרוס את המתודה equals().

public class Person {
    private String name;
    private int age;
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Person person = (Person) obj;
        return age == person.age && name.equals(person.name);
    }
}

השיטה equals() פועלת לפי דפוס מקובל: תחילה בודקים אם מדובר באותו אובייקט, לאחר מכן מוודאים את הסוג, ולבסוף משווים בין השדות הרלוונטיים.

בכל פעם שדורסים את equals(), חייבים לדרוס גם את hashCode(). זהו חוזה ב-Java: לאובייקטים שווים חייב להיות אותו קוד גיבוב. אוספים מבוססי גיבוב כמו HashMap ו-HashSet מסתמכים על הכלל הזה כדי לפעול כראוי.

@Override
public int hashCode() {
    return Objects.hash(name, age);
}

שיטת העזר Objects.hash() יוצרת קוד גיבוב מאותם שדות שבהם משתמשת equals(). אם לשני אובייקטים מסוג Person יש אותו שם ואותו גיל, הם ייחשבו שווים וייצרו קודי גיבוב זהים, וכך יובטחו התנהגויות עקביות באוספים.

challenge icon

אתגר

קל

בואו נבנה מערכת לניהול רשומות תלמידים שמממשת כראוי שוויון בין אובייקטים. תיצרו מחלקה Student שבה שני תלמידים נחשבים שווים אם יש להם אותו מזהה תלמיד ואותו שם, בלי קשר לשאלה אם הם אותו אובייקט בזיכרון.

תארגנו את הקוד שלכם בשני קבצים:

  • Student.java: צרו מחלקה שמייצגת תלמיד, עם שלושה שדות פרטיים: studentId (String), name (String), ו-gpa (double). כללו בנאי לאתחול כל השדות ומתודות getter לכל שדה.

    דרסו את המתודה equals() כך ששני אובייקטים מסוג Student ייחשבו שווים כאשר יש להם אותו studentId וגם אותו name. פעלו לפי התבנית המקובלת: בדקו אם מדובר באותה הפניה, בדקו אם הערך הוא null ואם הטיפוס תואם, ואז השוו בין השדות הרלוונטיים.

    דרסו את המתודה hashCode() באמצעות Objects.hash() עם אותם שדות שבהם משתמשים ב-equals(). זכרו לייבא את java.util.Objects בראש הקובץ.

  • Main.java: הפעילו את מחלקת Student שלכם על ידי השוואה בין אובייקטים של תלמידים. תקבלו שש קלטים שמייצגים שני תלמידים: המזהה, השם והממוצע של התלמיד הראשון, ולאחר מכן המזהה, השם והממוצע של התלמיד השני.

    צרו את שני אובייקטי Student, ואז בצעו שלוש השוואות והדפיסו את התוצאות:

    1. הדפיסו Same reference: ולאחר מכן אם התלמיד הראשון שווה לעצמו (התוצאה אמורה להיות true תמיד)
    2. הדפיסו Content equality: ולאחר מכן אם התלמיד הראשון שווה לתלמיד השני (בהתאם למימוש שלכם של equals)
    3. הדפיסו Hash codes match: ולאחר מכן אם לשני התלמידים יש אותו קוד גיבוב

תקבלו שש קלטים: המזהה של התלמיד הראשון (String), השם של התלמיד הראשון (String), הממוצע של התלמיד הראשון (double), המזהה של התלמיד השני (String), השם של התלמיד השני (String), והממוצע של התלמיד השני (double).

שימו לב שכאשר לשני תלמידים יש מזהים ושמות זהים, גם equals() מחזירה true וגם קודי הגיבוב שלהם זהים. זהו החוזה שעליכם לקיים!

נסו בעצמכם

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // קרא את נתוני הסטודנט הראשון
        String id1 = scanner.nextLine();
        String name1 = scanner.nextLine();
        double gpa1 = scanner.nextDouble();
        scanner.nextLine(); // צרוך את תו השורה החדשה
        
        // קרא את נתוני הסטודנט השני
        String id2 = scanner.nextLine();
        String name2 = scanner.nextLine();
        double gpa2 = scanner.nextDouble();
        
        // TODO: צור שני אובייקטים מסוג Student באמצעות נתוני הקלט
        
        // TODO: הדפס "Same reference: " ולאחר מכן האם student1 שווה לעצמו
        
        // TODO: הדפס "Content equality: " ולאחר מכן האם student1 שווה ל-student2
        
        // TODO: הדפס "Hash codes match: " ולאחר מכן האם לשני הסטודנטים יש אותו קוד גיבוב
    }
}
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר Java אונליין